This is a patch file against 0.1.3. Change to directory g10-0.1.3 (or however you renamed it) and give this command: zcat somepath/g10-0.2.0.diff.gz | patch -p1 It is a good idea to rename your current directory to g10-0.2.0 now. Prereq: 0.1.3 diff -urN g10-0.1.3/VERSION g10-0.2.0/VERSION --- g10-0.1.3/VERSION Mon Jan 12 10:54:02 1998 +++ g10-0.2.0/VERSION Sun Jan 25 19:55:46 1998 @@ -1 +1 @@ -0.1.3 +0.2.0 diff -urN g10-0.1.3/NEWS g10-0.2.0/NEWS --- g10-0.1.3/NEWS Mon Jan 12 10:48:47 1998 +++ g10-0.2.0/NEWS Sun Jan 25 19:55:35 1998 @@ -1,4 +1,23 @@ + * The logic to handle the web of trust is now implemented. It is + has some bugs; but I'm going to change the algorithm anyway. + It works by calculating the trustlevel on the fly. It may ask + you to provide trust parameters if the calculated trust probability + is too low. I will write a paper which discusses this new approach. + + * a couple of changes to the configure script. + + * New option "--quick-random" which uses a much quicker random + number generator. Keys generated while this option is in effect + are flags with "INSECURE!" in the user-id. This is a development + 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. diff -urN g10-0.1.3/README g10-0.2.0/README --- g10-0.1.3/README Mon Jan 12 10:52:00 1998 +++ g10-0.2.0/README Sun Jan 25 19:49:46 1998 @@ -11,14 +11,11 @@ * Some features are not yet implemented - I provide this version as a reality check to start discussion. Please subscribe to g10@net.lut.ac.uk by sending a mail with the word "subscribe" in the body to "g10-request@net.lut.ac.uk". - See the file COPYING for copyright and warranty information. - Due to the fact that G10 does not use use any patented algorithm, it cannot be compatible to old PGP versions, because those use IDEA (which is worldwide patented) and RSA (which is patented in @@ -57,15 +54,10 @@ 4) You end up with a binary "g10" in /usr/local/bin + 5) create a directory ".g10" under your hoem directory ("mkdir ~/.g10") - Resources - --------- - G10 needs a directory "~/.g10" to store the default keyrings - and other files. - - Key Generation -------------- @@ -75,8 +67,9 @@ good random numbers for prime number generation, it uses a /dev/random which will emit only bytes if the kernel can gather enough entropy. If you see no progress, you should start some other activities such - as mouse moves or a "find /". Because we have no hardware device - to generate random we have to use this method. + as mouse moves, "find /" or using the keyboard (on another window). + Because we have no hardware device to generate random we have to use + this method. Key generation shows progress by printing different characters to stderr: @@ -109,17 +102,18 @@ g10 --sign-key Donald - To sign the key of of "Donald" with your default userid + This let you sign the key of "Donald" with your default userid. g10 --sign-key -u Karl -u Joe Donald - To sign the key of of "Donald" with the userids of "Karl" and "Joe". + This let you sign the key of of "Donald" with the userids of "Karl" + and "Joe". All existing signatures are checked, if some are invalid, a menu is offered to delete some of them, and the you are asked for every user wether you want to sign this key. - You may remove a signature at any time by usiing the option "--edit-sig", - which also asks for the sigs to remove. + You may remove a signature at any time using the option "--edit-sig", + which asks for the sigs to remove. Sign @@ -166,17 +160,6 @@ Ditto, but sign the file with the user id "Suttner" - - Examine a data or key file - -------------------------- - - g10 --list-packets datafile - - Use this to list the contents of a data file. If the file is encrypted - you are asked for the passphrase, so that G10 is able to look at the - inner structure of a encrypted packet. - - Batch mode ---------- If you use the option "--batch", G10 runs in non-interactive mode and @@ -185,7 +168,7 @@ you can use the option "--passhrase-fd n", which works like PGPs PGPPASSFD. - Batch mode also causes PGP to terminate as soon as a BAD signature is + Batch mode also causes G10 to terminate as soon as a BAD signature is detected. @@ -196,6 +179,57 @@ stderr to get detailed informations about the errors. + Esoteric commands + ----------------- + + g10 --list-packets datafile + + Use this to list the contents of a data file. If the file is encrypted + you are asked for the passphrase, so that G10 is able to look at the + inner structure of a encrypted packet. + + --quick-random + + Do not use the stroing random generator but a faster one. This can be + used to generate keys for tests; those are marked as insecure. + + --list-trustdb + + List the contents of the trustdb in a human readable format + + --list-trustdb + + List the tree of certificates for the given usernames + + --list-trust-path depth username + + List the possible trust paths for the given username, up to the specified + depth. If depth is negative, duplicate introducers are not listed, + because those would increase the trust probabilty only minimal. + (you must use the special option "--" to stop option parsing when + using a negative number). This option may create new entries in the + trustdb. + + --print-mds filenames + + List all available message digest values for the fiven filenames + + --gen-prime n + + Generate and print a simple prime number of size n + + --gen-prime n q + + Generate a prime number suitable for ElGamal signatures of size n with + a q as largest primefactor of n-1. + + --gen-prime n q 1 + + Ditto, but calculate a generator too. + + + For more options/commands see the file g10/OPTIONS. + Debug Flags ----------- @@ -213,7 +247,7 @@ 32 memory allocation stuff 64 caching 128 show memory statistics at exit - + 256 trust verification stuff Other Notes diff -urN g10-0.1.3/TODO g10-0.2.0/TODO --- g10-0.1.3/TODO Mon Jan 12 10:33:34 1998 +++ g10-0.2.0/TODO Sun Jan 25 19:16:20 1998 @@ -39,4 +39,9 @@ * Burn the buffers used by fopen(). + * bug: g10/trustdb.c#build_sigrecs caled to often by do_list_path + and remove the bad kludge. Maybe we should put all sigs into the trustdb + and mark them as valid/invalid/nopubkey, and how do we check, that + we have a self-signature -> put this stuff into a kind of directory + record, as it does not belong to the pubkey record? diff -urN g10-0.1.3/acconfig.h g10-0.2.0/acconfig.h --- g10-0.1.3/acconfig.h Mon Jan 5 13:54:15 1998 +++ g10-0.2.0/acconfig.h Thu Jan 22 18:44:33 1998 @@ -50,4 +50,20 @@ @BOTTOM@ +/* The AC_CHECK_SIZEOF() fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT + #undef SIZEOF_UNSIGNED_SHORT + #define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT + #undef SIZEOF_UNSIGNED_INT + #define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG + #undef SIZEOF_UNSIGNED_LONG + #define SIZEOF_UNSIGNED_LONG 4 +#endif + + #endif /*G10_CONFIG_H*/ diff -urN g10-0.1.3/cipher/Makefile.in g10-0.2.0/cipher/Makefile.in --- g10-0.1.3/cipher/Makefile.in Mon Jan 12 11:01:42 1998 +++ g10-0.2.0/cipher/Makefile.in Sun Jan 25 20:22:13 1998 @@ -202,8 +202,9 @@ ../include/../cipher/elgamal.h primegen.o: primegen.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ - ../include/memory.h ../include/cipher.h ../include/../cipher/md5.h \ + ../include/memory.h ../include/cipher.h ../include/../cipher/md.h \ ../include/../cipher/rmd.h ../include/../cipher/sha1.h \ + ../include/../cipher/md5.h ../include/../cipher/rsa.h \ ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ ../include/../cipher/elgamal.h random.o: random.c ../include/util.h ../include/types.h \ @@ -212,7 +213,7 @@ ../include/../cipher/rmd.h ../include/../cipher/sha1.h \ ../include/../cipher/md5.h ../include/../cipher/rsa.h \ ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ - ../include/../cipher/elgamal.h + ../include/../cipher/elgamal.h ../include/ttyio.h rmd160.o: rmd160.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h rmd.h diff -urN g10-0.1.3/cipher/blowfish.c g10-0.2.0/cipher/blowfish.c --- g10-0.1.3/cipher/blowfish.c Tue Jan 6 21:59:51 1998 +++ g10-0.2.0/cipher/blowfish.c Fri Jan 16 12:16:50 1998 @@ -26,6 +26,7 @@ * key "abcdefghijklmnopqrstuvwxyz"; * plain "BLOWFISH" * cipher 32 4E D0 FE F4 13 A2 03 + * */ #include @@ -385,6 +386,9 @@ BLOWFISH_context c; byte plain[] = "BLOWFISH"; byte buffer[8]; + byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; + byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; + byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 ); encrypt_block( &c, buffer, plain ); @@ -393,6 +397,14 @@ decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) log_bug("blowfish failed\n"); + + blowfish_setkey( &c, key3, 8 ); + encrypt_block( &c, buffer, plain3 ); + if( memcmp( buffer, cipher3, 8 ) ) + log_error("wrong blowfish encryption (3)\n"); + decrypt_block( &c, buffer, buffer ); + if( memcmp( buffer, plain3, 8 ) ) + log_bug("blowfish failed (3)\n"); } @@ -400,7 +412,7 @@ void blowfish_setkey( BLOWFISH_context *c, byte *key, unsigned keylen ) { - int i, j, k; + int i, j; u32 data, datal, datar; static int initialized; diff -urN g10-0.1.3/cipher/md.c g10-0.2.0/cipher/md.c --- g10-0.1.3/cipher/md.c Mon Jan 12 10:27:52 1998 +++ g10-0.2.0/cipher/md.c Fri Jan 16 12:22:07 1998 @@ -144,7 +144,7 @@ if( algo == DIGEST_ALGO_MD5 ) return md5_read( &a->md5 ); } - log_bug(NULL); + BUG(); } int diff -urN g10-0.1.3/cipher/md5.c g10-0.2.0/cipher/md5.c --- g10-0.1.3/cipher/md5.c Fri Jan 9 10:17:55 1998 +++ g10-0.2.0/cipher/md5.c Fri Jan 16 12:16:48 1998 @@ -73,7 +73,6 @@ #endif -static void Init( MD5_CONTEXT *mdContext); static void Transform(u32 *buf,u32 *in); static byte PADDING[64] = { diff -urN g10-0.1.3/cipher/misc.c g10-0.2.0/cipher/misc.c --- g10-0.1.3/cipher/misc.c Fri Jan 9 13:51:30 1998 +++ g10-0.2.0/cipher/misc.c Fri Jan 16 12:20:45 1998 @@ -67,7 +67,7 @@ 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 @@ 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 @@ 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; diff -urN g10-0.1.3/cipher/primegen.c g10-0.2.0/cipher/primegen.c --- g10-0.1.3/cipher/primegen.c Sun Dec 28 13:20:58 1997 +++ g10-0.2.0/cipher/primegen.c Fri Jan 16 12:22:54 1998 @@ -319,8 +319,6 @@ 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 @@ array[i] = 1; return; } - log_bug(NULL); + BUG(); } for(j=1; j < n; j++ ) { diff -urN g10-0.1.3/cipher/random.c g10-0.2.0/cipher/random.c --- g10-0.1.3/cipher/random.c Mon Jan 12 10:01:48 1998 +++ g10-0.2.0/cipher/random.c Wed Jan 21 18:56:53 1998 @@ -30,6 +30,7 @@ #include #include "util.h" #include "cipher.h" +#include "ttyio.h" struct cache { int len; @@ -41,6 +42,18 @@ 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 @@ 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; @@ -155,6 +167,10 @@ #else /* not HAVE_DEV_RANDOM */ +#ifndef RAND_MAX /* for SunOS */ + #define RAND_MAX 32767 +#endif + static void fill_buffer( byte *buffer, size_t length, int level ) { @@ -166,11 +182,20 @@ "it compile - it is in no way a strong RNG!\n\n" "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"); initialized=1; + #ifdef HAVE_RAND srand(make_timestamp()*getpid()); + #else + srandom(make_timestamp()*getpid()); + #endif } + #ifdef HAVE_RAND while( length-- ) *buffer++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); + #else + while( length-- ) + *buffer++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); + #endif } #endif diff -urN g10-0.1.3/config.h.in g10-0.2.0/config.h.in --- g10-0.1.3/config.h.in Wed Jan 7 20:13:35 1998 +++ g10-0.2.0/config.h.in Thu Jan 22 18:44:57 1998 @@ -72,6 +72,9 @@ /* The number of bytes in a unsigned short. */ #undef SIZEOF_UNSIGNED_SHORT +/* Define if you have the rand function. */ +#undef HAVE_RAND + /* Define if you have the stpcpy function. */ #undef HAVE_STPCPY @@ -81,6 +84,9 @@ /* Define if you have the strlwr function. */ #undef HAVE_STRLWR +/* Define if you have the strtoul function. */ +#undef HAVE_STRTOUL + /* Define if you have the tcgetattr function. */ #undef HAVE_TCGETATTR @@ -89,6 +95,22 @@ /* Define if you have the header file. */ #undef HAVE_ZLIB_H + + +/* The AC_CHECK_SIZEOF() fails for some machines. + * we provide some fallback values here */ +#if !SIZEOF_UNSIGNED_SHORT + #undef SIZEOF_UNSIGNED_SHORT + #define SIZEOF_UNSIGNED_SHORT 2 +#endif +#if !SIZEOF_UNSIGNED_INT + #undef SIZEOF_UNSIGNED_INT + #define SIZEOF_UNSIGNED_INT 4 +#endif +#if !SIZEOF_UNSIGNED_LONG + #undef SIZEOF_UNSIGNED_LONG + #define SIZEOF_UNSIGNED_LONG 4 +#endif #endif /*G10_CONFIG_H*/ diff -urN g10-0.1.3/configure g10-0.2.0/configure --- g10-0.1.3/configure Mon Jan 12 11:01:13 1998 +++ g10-0.2.0/configure Thu Jan 22 18:45:01 1998 @@ -542,7 +542,7 @@ -VERSION=`cat ./VERSION` +VERSION=`cat $srcdir/VERSION` PACKAGE=g10 @@ -566,8 +566,8 @@ #define M_DEBUG 1 EOF - CFLAGS=-g fi +CFLAGS="-g -Wall" @@ -1213,57 +1213,15 @@ fi done -for ac_hdr in zlib.h -do -ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1221: checking for $ac_hdr" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext < -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1231: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` - cat >> confdefs.h <&6 -echo "configure: warning: zlib missing - creating without ZLIB support!" 1>&2 - -fi -done - echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:1262: checking for working const" >&5 +echo "configure:1220: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -1333,21 +1291,21 @@ fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1337: checking for inline" >&5 +echo "configure:1295: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1309: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -1373,12 +1331,12 @@ esac echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1377: checking for size_t" >&5 +echo "configure:1335: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -1411,14 +1369,14 @@ echo "configure: warning: cross compiling; assuming little endianess" 1>&2 fi echo $ac_n "checking for little endianess""... $ac_c" 1>&6 -echo "configure:1415: checking for little endianess" >&5 +echo "configure:1373: checking for little endianess" >&5 if eval "test \"`echo '$''{'ac_cv_c_littleendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_littleendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -1429,11 +1387,11 @@ #endif ; return 0; } EOF -if { (eval echo configure:1433: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1391: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -1444,7 +1402,7 @@ #endif ; return 0; } EOF -if { (eval echo configure:1448: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1406: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_littleendian=no else @@ -1464,7 +1422,7 @@ ac_cv_c_littleendian=yes else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1439: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_littleendian=yes else @@ -1508,12 +1466,12 @@ echo $ac_n "checking for byte typedef""... $ac_c" 1>&6 -echo "configure:1512: checking for byte typedef" >&5 +echo "configure:1470: checking for byte typedef" >&5 if eval "test \"`echo '$''{'wk_cv_typedef_byte'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1524,7 +1482,7 @@ ; return 0; } EOF -if { (eval echo configure:1528: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1486: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wk_cv_typedef_byte=yes else @@ -1545,12 +1503,12 @@ fi echo $ac_n "checking for ushort typedef""... $ac_c" 1>&6 -echo "configure:1549: checking for ushort typedef" >&5 +echo "configure:1507: checking for ushort typedef" >&5 if eval "test \"`echo '$''{'wk_cv_typedef_ushort'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1561,7 +1519,7 @@ ; return 0; } EOF -if { (eval echo configure:1565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1523: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wk_cv_typedef_ushort=yes else @@ -1582,12 +1540,12 @@ fi echo $ac_n "checking for ulong typedef""... $ac_c" 1>&6 -echo "configure:1586: checking for ulong typedef" >&5 +echo "configure:1544: checking for ulong typedef" >&5 if eval "test \"`echo '$''{'wk_cv_typedef_ulong'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1598,7 +1556,7 @@ ; return 0; } EOF -if { (eval echo configure:1602: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1560: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wk_cv_typedef_ulong=yes else @@ -1619,12 +1577,12 @@ fi echo $ac_n "checking for u16 typedef""... $ac_c" 1>&6 -echo "configure:1623: checking for u16 typedef" >&5 +echo "configure:1581: checking for u16 typedef" >&5 if eval "test \"`echo '$''{'wk_cv_typedef_u16'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1635,7 +1593,7 @@ ; return 0; } EOF -if { (eval echo configure:1639: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wk_cv_typedef_u16=yes else @@ -1656,12 +1614,12 @@ fi echo $ac_n "checking for u32 typedef""... $ac_c" 1>&6 -echo "configure:1660: checking for u32 typedef" >&5 +echo "configure:1618: checking for u32 typedef" >&5 if eval "test \"`echo '$''{'wk_cv_typedef_u32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1672,7 +1630,7 @@ ; return 0; } EOF -if { (eval echo configure:1676: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1634: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wk_cv_typedef_u32=yes else @@ -1694,7 +1652,7 @@ echo $ac_n "checking size of unsigned short""... $ac_c" 1>&6 -echo "configure:1698: checking size of unsigned short" >&5 +echo "configure:1656: checking size of unsigned short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1702,7 +1660,7 @@ ac_cv_sizeof_unsigned_short=2 else cat > conftest.$ac_ext < main() @@ -1713,7 +1671,7 @@ exit(0); } EOF -if { (eval echo configure:1717: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_short=`cat conftestval` else @@ -1733,7 +1691,7 @@ echo $ac_n "checking size of unsigned int""... $ac_c" 1>&6 -echo "configure:1737: checking size of unsigned int" >&5 +echo "configure:1695: checking size of unsigned int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1741,7 +1699,7 @@ ac_cv_sizeof_unsigned_int=4 else cat > conftest.$ac_ext < main() @@ -1752,7 +1710,7 @@ exit(0); } EOF -if { (eval echo configure:1756: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_int=`cat conftestval` else @@ -1772,7 +1730,7 @@ echo $ac_n "checking size of unsigned long""... $ac_c" 1>&6 -echo "configure:1776: checking size of unsigned long" >&5 +echo "configure:1734: checking size of unsigned long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_unsigned_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1780,7 +1738,7 @@ ac_cv_sizeof_unsigned_long=4 else cat > conftest.$ac_ext < main() @@ -1791,7 +1749,7 @@ exit(0); } EOF -if { (eval echo configure:1795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1753: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_unsigned_long=`cat conftestval` else @@ -1811,16 +1769,21 @@ +if test "$ac_cv_sizeof_unsigned_short" = "0" \ + || test "$ac_cv_sizeof_unsigned_int" = "0" \ + || test "$ac_cv_sizeof_unsigned_long" = "0"; then + echo "configure: warning: Hmmm, something is wrong with the sizes - using defaults" 1>&2; +fi echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:1819: checking for vprintf" >&5 +echo "configure:1782: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1810: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else @@ -1867,12 +1830,12 @@ if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:1871: checking for _doprnt" >&5 +echo "configure:1834: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1862: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else @@ -1919,15 +1882,15 @@ fi -for ac_func in strerror stpcpy strlwr tcgetattr +for ac_func in strerror stpcpy strlwr tcgetattr rand strtoul do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1926: checking for $ac_func" >&5 +echo "configure:1889: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1975,8 +1938,11 @@ done + + + echo $ac_n "checking for random device""... $ac_c" 1>&6 -echo "configure:1980: checking for random device" >&5 +echo "configure:1946: checking for random device" >&5 if eval "test \"`echo '$''{'ac_cv_have_dev_random'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1994,7 +1960,7 @@ echo $ac_n "checking for mpi assembler functions""... $ac_c" 1>&6 -echo "configure:1998: checking for mpi assembler functions" >&5 +echo "configure:1964: checking for mpi assembler functions" >&5 mpi_config_done="no" if eval "test \"`echo '$''{'ac_cv_mpi_config_done'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2006,8 +1972,8 @@ echo "$ac_t""done" 1>&6 else ac_cv_mpi_config_done="" -if test -f ./mpi/config.links ; then - . ./mpi/config.links +if test -f $srcdir/mpi/config.links ; then + . $srcdir/mpi/config.links ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" ac_cv_mpi_config_done="yes" @@ -2029,14 +1995,57 @@ +for ac_hdr in zlib.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2003: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2013: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +echo "configure: warning: zlib missing - creating without ZLIB support!" 1>&2 + +fi +done + + CIPHER_EXTRA_OBJS="" CIPHER_EXTRA_DIST="" echo $ac_n "checking for extra cipher modules""... $ac_c" 1>&6 -echo "configure:2036: checking for extra cipher modules" >&5 +echo "configure:2045: checking for extra cipher modules" >&5 if eval "test \"`echo '$''{'ac_cv_have_rsa_cipher'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test -f cipher/rsa.c && test -f cipher/rsa.h; then + if test -f $srcdir/cipher/rsa.c && test -f $srcdir/cipher/rsa.h; then ac_cv_have_rsa_cipher=yes; else ac_cv_have_rsa_cipher=no; fi fi diff -urN g10-0.1.3/configure.in g10-0.2.0/configure.in --- g10-0.1.3/configure.in Wed Jan 7 20:13:25 1998 +++ g10-0.2.0/configure.in Thu Jan 22 18:41:16 1998 @@ -8,7 +8,7 @@ AC_CONFIG_HEADER(config.h) -VERSION=`cat ./VERSION` +VERSION=`cat $srcdir/VERSION` PACKAGE=g10 AC_SUBST(VERSION) AC_SUBST(PACKAGE) @@ -19,8 +19,8 @@ [ --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 @@ -90,10 +90,6 @@ dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h) -AC_CHECK_HEADERS(zlib.h, - [LIBS="$LIBS -lz"], - AC_MSG_WARN([zlib missing - creating without ZLIB support!]) - ) dnl Checks for typedefs, structures, and compiler characteristics. @@ -150,12 +146,20 @@ AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) +if test "$ac_cv_sizeof_unsigned_short" = "0" \ + || test "$ac_cv_sizeof_unsigned_int" = "0" \ + || test "$ac_cv_sizeof_unsigned_long" = "0"; then + AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); +fi dnl Checks for library functions. AC_FUNC_VPRINTF -AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr) +AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr rand strtoul) + + + dnl check wether we have a random device AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, @@ -175,8 +179,8 @@ AC_MSG_RESULT(done) else ac_cv_mpi_config_done="" -if test -f ./mpi/config.links ; then - . ./mpi/config.links +if test -f $srcdir/mpi/config.links ; then + . $srcdir/mpi/config.links ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" AC_LINK_FILES( ${mpi_ln_src}, ${mpi_ln_dst} ) ac_cv_mpi_config_done="yes" @@ -198,11 +202,18 @@ AC_SUBST(MPI_EXTRA_ASM_OBJS) +dnl Do we have zlib? Must do it here because Solaris failed +dnl when compiling a conftest (due to the "-lz" from LIBS). +AC_CHECK_HEADERS(zlib.h, + [LIBS="$LIBS -lz"], + AC_MSG_WARN([zlib missing - creating without ZLIB support!]) + ) + dnl checking whether we have other cipher source files CIPHER_EXTRA_OBJS="" CIPHER_EXTRA_DIST="" AC_CACHE_CHECK(for extra cipher modules, ac_cv_have_rsa_cipher, -[if test -f cipher/rsa.c && test -f cipher/rsa.h; then +[if test -f $srcdir/cipher/rsa.c && test -f $srcdir/cipher/rsa.h; then ac_cv_have_rsa_cipher=yes; else ac_cv_have_rsa_cipher=no; fi]) if test $ac_cv_have_rsa_cipher = yes; then AC_DEFINE(HAVE_RSA_CIPHER) diff -urN g10-0.1.3/g10/Makefile.am g10-0.2.0/g10/Makefile.am --- g10-0.1.3/g10/Makefile.am Thu Jan 8 10:08:56 1998 +++ g10-0.2.0/g10/Makefile.am Wed Jan 14 17:07:47 1998 @@ -40,6 +40,7 @@ seckey-cert.c \ seskey.c \ sign.c \ + import.c \ comment.c \ sig-check.c diff -urN g10-0.1.3/g10/Makefile.in g10-0.2.0/g10/Makefile.in --- g10-0.1.3/g10/Makefile.in Mon Jan 12 11:01:43 1998 +++ g10-0.2.0/g10/Makefile.in Sun Jan 25 20:22:13 1998 @@ -78,6 +78,7 @@ seckey-cert.c \ seskey.c \ sign.c \ + import.c \ comment.c \ sig-check.c @@ -103,7 +104,8 @@ 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 @@ -197,8 +199,9 @@ armor.o: armor.c ../include/errors.h ../include/iobuf.h \ ../include/types.h ../include/memory.h ../include/util.h \ ../include/mpi.h filter.h ../include/cipher.h \ - ../include/../cipher/md5.h ../include/../cipher/rmd.h \ - ../include/../cipher/sha1.h ../include/../cipher/blowfish.h \ + ../include/../cipher/md.h ../include/../cipher/rmd.h \ + ../include/../cipher/sha1.h ../include/../cipher/md5.h \ + ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h packet.h \ options.h build-packet.o: build-packet.c packet.h ../include/types.h \ @@ -218,16 +221,18 @@ ../include/../cipher/elgamal.h packet.h options.h comment.o: comment.c options.h packet.h ../include/types.h \ ../include/iobuf.h ../include/mpi.h ../include/memory.h \ - ../include/cipher.h ../include/../cipher/md5.h \ + ../include/cipher.h ../include/../cipher/md.h \ ../include/../cipher/rmd.h ../include/../cipher/sha1.h \ + ../include/../cipher/md5.h ../include/../cipher/rsa.h \ ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ ../include/../cipher/elgamal.h filter.h ../include/errors.h \ ../include/util.h main.h keydb.h compress.o: compress.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ - ../include/../cipher/md5.h ../include/../cipher/rmd.h \ - ../include/../cipher/sha1.h ../include/../cipher/blowfish.h \ + ../include/../cipher/md.h ../include/../cipher/rmd.h \ + ../include/../cipher/sha1.h ../include/../cipher/md5.h \ + ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ options.h elg.o: elg.c options.h packet.h ../include/types.h ../include/iobuf.h \ @@ -239,11 +244,12 @@ ../include/errors.h keydb.h ../include/util.h main.h encode.o: encode.c options.h packet.h ../include/types.h \ ../include/iobuf.h ../include/mpi.h ../include/memory.h \ - ../include/cipher.h ../include/../cipher/md5.h \ + ../include/cipher.h ../include/../cipher/md.h \ ../include/../cipher/rmd.h ../include/../cipher/sha1.h \ - ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ - ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ - ../include/errors.h keydb.h ../include/util.h main.h + ../include/../cipher/md5.h ../include/../cipher/rsa.h \ + ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ + ../include/../cipher/elgamal.h filter.h ../include/errors.h keydb.h \ + ../include/util.h main.h encr-data.o: encr-data.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ @@ -266,14 +272,23 @@ ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ ../include/util.h ../include/errors.h main.h keydb.h options.h \ - trustdb.h + trustdb.h ../include/ttyio.h getkey.o: getkey.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ - ../include/../cipher/md5.h ../include/../cipher/rmd.h \ - ../include/../cipher/sha1.h ../include/../cipher/blowfish.h \ + ../include/../cipher/md.h ../include/../cipher/rmd.h \ + ../include/../cipher/sha1.h ../include/../cipher/md5.h \ + ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ keydb.h options.h +import.o: import.c options.h packet.h ../include/types.h \ + ../include/iobuf.h ../include/mpi.h ../include/memory.h \ + ../include/cipher.h ../include/../cipher/md.h \ + ../include/../cipher/rmd.h ../include/../cipher/sha1.h \ + ../include/../cipher/md5.h ../include/../cipher/rsa.h \ + ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ + ../include/../cipher/elgamal.h filter.h ../include/errors.h keydb.h \ + ../include/util.h trustdb.h kbnode.o: kbnode.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ @@ -341,7 +356,7 @@ ../include/../cipher/md5.h ../include/../cipher/rsa.h \ ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ ../include/../cipher/elgamal.h filter.h ../include/errors.h keydb.h \ - ../include/util.h trustdb.h + ../include/util.h trustdb.h ../include/ttyio.h plaintext.o: plaintext.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h options.h packet.h ../include/cipher.h \ @@ -360,8 +375,9 @@ ringedit.o: ringedit.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ - ../include/../cipher/md5.h ../include/../cipher/rmd.h \ - ../include/../cipher/sha1.h ../include/../cipher/blowfish.h \ + ../include/../cipher/md.h ../include/../cipher/rmd.h \ + ../include/../cipher/sha1.h ../include/../cipher/md5.h \ + ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ keydb.h rsa.o: rsa.c options.h packet.h ../include/types.h ../include/iobuf.h \ @@ -374,8 +390,9 @@ seckey-cert.o: seckey-cert.c ../include/util.h ../include/types.h \ ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h packet.h ../include/cipher.h \ - ../include/../cipher/md5.h ../include/../cipher/rmd.h \ - ../include/../cipher/sha1.h ../include/../cipher/blowfish.h \ + ../include/../cipher/md.h ../include/../cipher/rmd.h \ + ../include/../cipher/sha1.h ../include/../cipher/md5.h \ + ../include/../cipher/rsa.h ../include/../cipher/blowfish.h \ ../include/../cipher/gost.h ../include/../cipher/elgamal.h filter.h \ keydb.h seskey.o: seskey.c ../include/util.h ../include/types.h \ @@ -422,7 +439,7 @@ ../include/../cipher/md5.h ../include/../cipher/rsa.h \ ../include/../cipher/blowfish.h ../include/../cipher/gost.h \ ../include/../cipher/elgamal.h filter.h ../include/util.h trustdb.h \ - options.h + options.h main.h info: diff -urN g10-0.1.3/g10/armor.c g10-0.2.0/g10/armor.c --- g10-0.1.3/g10/armor.c Tue Dec 23 22:29:19 1997 +++ g10-0.2.0/g10/armor.c Fri Jan 16 12:52:52 1998 @@ -275,7 +275,7 @@ { 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ } 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 @@ 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-- ) { diff -urN g10-0.1.3/g10/build-packet.c g10-0.2.0/g10/build-packet.c --- g10-0.1.3/g10/build-packet.c Fri Jan 9 13:36:58 1998 +++ g10-0.2.0/g10/build-packet.c Wed Jan 21 11:52:37 1998 @@ -50,7 +50,8 @@ 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 @@ 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 ); @@ -143,9 +147,11 @@ static int do_comment( IOBUF out, int ctb, PKT_comment *rem ) { - write_header(out, ctb, rem->len); - if( iobuf_write( out, rem->data, rem->len ) ) - return G10ERR_WRITE_FILE; + if( !opt.no_comment ) { + write_header(out, ctb, rem->len); + if( iobuf_write( out, rem->data, rem->len ) ) + return G10ERR_WRITE_FILE; + } return 0; } @@ -164,7 +170,10 @@ 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 +191,7 @@ 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 +211,7 @@ int rc = 0; int c; IOBUF a = iobuf_temp(); + FILE *fp = fopen("dump.pkc", "a"); /* build the packet */ init_packet(&pkt); @@ -209,9 +219,11 @@ 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 +234,10 @@ 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 +277,7 @@ 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 +380,7 @@ 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 +448,6 @@ if( iobuf_write_temp( out, a ) ) rc = G10ERR_WRITE_FILE; - leave: iobuf_close(a); return rc; } @@ -482,20 +496,39 @@ 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 ) { @@ -511,6 +544,36 @@ iobuf_put(out, len >> 8 ); if( iobuf_put(out, len ) ) return -1; + } + 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; } diff -urN g10-0.1.3/g10/comment.c g10-0.2.0/g10/comment.c --- g10-0.1.3/g10/comment.c Tue Dec 16 16:10:39 1997 +++ g10-0.2.0/g10/comment.c Wed Jan 21 11:51:58 1998 @@ -57,9 +57,10 @@ KBNODE make_comment_node( const char *s ) { - PACKET *pkt = m_alloc_clear( sizeof *pkt ); + PACKET *pkt; size_t n = strlen(s); + pkt = m_alloc_clear( sizeof *pkt ); pkt->pkttype = PKT_COMMENT; pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 ); pkt->pkt.comment->len = n; diff -urN g10-0.1.3/g10/compress.c g10-0.2.0/g10/compress.c --- g10-0.1.3/g10/compress.c Mon Dec 22 22:51:33 1997 +++ g10-0.2.0/g10/compress.c Fri Jan 16 12:48:39 1998 @@ -41,7 +41,6 @@ init_compress( compress_filter_context_t *zfx, z_stream *zs ) { int rc; - byte *inbuf, *outbuf; int level; @@ -102,9 +101,6 @@ 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 @@ 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 ) { diff -urN g10-0.1.3/g10/encode.c g10-0.2.0/g10/encode.c --- g10-0.1.3/g10/encode.c Wed Jan 7 17:42:43 1998 +++ g10-0.2.0/g10/encode.c Fri Jan 16 12:48:40 1998 @@ -159,7 +159,7 @@ { IOBUF inp = NULL, out = NULL; PACKET pkt; - PKT_plaintext *pt; + PKT_plaintext *pt = NULL; int rc = 0; u32 filesize; cipher_filter_context_t cfx; @@ -244,7 +244,8 @@ iobuf_cancel(out); else iobuf_close(out); /* fixme: check returncode */ - pt->buf = NULL; + if( pt ) + pt->buf = NULL; free_packet(&pkt); m_free(cfx.dek); release_pkc_list( pkc_list ); @@ -264,7 +265,7 @@ 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 ) { @@ -316,7 +317,7 @@ 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; diff -urN g10-0.1.3/g10/free-packet.c g10-0.2.0/g10/free-packet.c --- g10-0.1.3/g10/free-packet.c Fri Jan 9 10:20:04 1998 +++ g10-0.2.0/g10/free-packet.c Tue Jan 13 16:07:41 1998 @@ -57,18 +57,24 @@ } void -free_public_cert( PKT_public_cert *cert ) +release_public_cert_parts( PKT_public_cert *cert ) { if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { - mpi_free( cert->d.elg.p ); - mpi_free( cert->d.elg.g ); - mpi_free( cert->d.elg.y ); + mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL; + mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL; + mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL; } else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) { - mpi_free( cert->d.rsa.rsa_n ); - mpi_free( cert->d.rsa.rsa_e ); + mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL; + mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL; } - md_close( cert->mfx.md ); + md_close( cert->mfx.md ); cert->mfx.md = NULL; +} + +void +free_public_cert( PKT_public_cert *cert ) +{ + release_public_cert_parts( cert ); m_free(cert); } @@ -92,22 +98,28 @@ } void -free_secret_cert( PKT_secret_cert *cert ) +release_secret_cert_parts( PKT_secret_cert *cert ) { if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { - mpi_free( cert->d.elg.p ); - mpi_free( cert->d.elg.g ); - mpi_free( cert->d.elg.y ); - mpi_free( cert->d.elg.x ); + mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL; + mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL; + mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL; + mpi_free( cert->d.elg.x ); cert->d.elg.x = NULL; } else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) { - mpi_free( cert->d.rsa.rsa_n ); - mpi_free( cert->d.rsa.rsa_e ); - mpi_free( cert->d.rsa.rsa_d ); - mpi_free( cert->d.rsa.rsa_p ); - mpi_free( cert->d.rsa.rsa_q ); - mpi_free( cert->d.rsa.rsa_u ); + mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL; + mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL; + mpi_free( cert->d.rsa.rsa_d ); cert->d.rsa.rsa_d = NULL; + mpi_free( cert->d.rsa.rsa_p ); cert->d.rsa.rsa_p = NULL; + mpi_free( cert->d.rsa.rsa_q ); cert->d.rsa.rsa_q = NULL; + mpi_free( cert->d.rsa.rsa_u ); cert->d.rsa.rsa_u = NULL; } +} + +void +free_secret_cert( PKT_secret_cert *cert ) +{ + release_secret_cert_parts( cert ); m_free(cert); } @@ -240,4 +252,34 @@ pkt->pkt.generic = NULL; } +/**************** + * Returns 0 if they match. + */ +int +cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc ) +{ + if( pkc->timestamp != skc->timestamp ) + return -1; + if( pkc->valid_days != skc->valid_days ) + return -1; + if( pkc->pubkey_algo != skc->pubkey_algo ) + return -1; + + if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { + if( mpi_cmp( pkc->d.elg.p , skc->d.elg.p ) ) + return -1; + if( mpi_cmp( pkc->d.elg.g , skc->d.elg.g ) ) + return -1; + if( mpi_cmp( pkc->d.elg.y , skc->d.elg.y ) ) + return -1; + } + else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { + if( mpi_cmp( pkc->d.rsa.rsa_n , skc->d.rsa.rsa_n ) ) + return -1; + if( mpi_cmp( pkc->d.rsa.rsa_e , skc->d.rsa.rsa_e ) ) + return -1; + } + + return 0; +} diff -urN g10-0.1.3/g10/g10.c g10-0.2.0/g10/g10.c --- g10-0.1.3/g10/g10.c Fri Jan 9 13:40:22 1998 +++ g10-0.2.0/g10/g10.c Sun Jan 25 19:41:28 1998 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "packet.h" @@ -35,11 +36,13 @@ #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 @@ } 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,18 @@ { 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"}, + { 534, "no-comment", 0, "do not write comment packets"}, + { 535, "completes_needed", 1, "(default is 1)"}, + { 536, "marginals_needed", 1, "(default is 3)"}, {0} }; ARGPARSE_ARGS pargs; IOBUF a; - int rc; + int rc=0; int orig_argc; char **orig_argv; const char *fname, *fname_print; @@ -202,6 +221,8 @@ opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH; opt.def_pubkey_algo = PUBKEY_ALGO_ELGAMAL; opt.def_digest_algo = DIGEST_ALGO_RMD160; + opt.completes_needed = 1; + opt.marginals_needed = 3; /* check wether we have a config file on the commandline */ orig_argc = argc; @@ -316,9 +337,13 @@ 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; + case 534: opt.no_comment=1; break; + case 535: opt.completes_needed = pargs.r.ret_int; break; + case 536: opt.marginals_needed = pargs.r.ret_int; break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -341,9 +366,18 @@ log_error("selected digest algorithm is invalid\n"); errors++; } + if( opt.completes_needed < 1 ) { + log_error("completes_needed must be greater than 0\n"); + errors++; + } + if( opt.marginals_needed < 2 ) { + log_error("marginals_needed must be greater than 1\n"); + errors++; + } if( errors ) exit(2); + set_debug(); if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */ if( cmd == aKModeC ) { @@ -393,11 +427,15 @@ } } - 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 ) { @@ -424,17 +462,36 @@ break; case aSign: /* sign the given file */ - if( argc > 1 ) - usage(1); - if( (rc = sign_file(fname, detached_sig, locusr, 0, NULL)) ) - log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) ); + sl = NULL; + if( detached_sig ) { /* sign all files */ + for( ; argc; argc--, argv++ ) + add_to_strlist( &sl, *argv ); + } + else { + if( argc > 1 ) + usage(1); + if( argc ) { + sl = m_alloc_clear( sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + } + if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) + log_error("sign_file: %s\n", g10_errstr(rc) ); + free_strlist(sl); break; case aSignEncr: /* sign and encrypt the given file */ if( argc > 1 ) usage(1); - if( (rc = sign_file(fname, detached_sig, locusr, 1, remusr)) ) + if( argc ) { + sl = m_alloc_clear( sizeof *sl + strlen(fname)); + strcpy(sl->d, fname); + } + else + sl = NULL; + if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) ); + free_strlist(sl); break; @@ -468,7 +525,7 @@ 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; @@ -535,6 +592,32 @@ 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 "); + list_trust_path( atoi(*argv), argv[1] ); + break; + case aListPackets: opt.list_packets=1; default: @@ -612,8 +695,6 @@ 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 -urN g10-0.1.3/g10/getkey.c g10-0.2.0/g10/getkey.c --- g10-0.1.3/g10/getkey.c Tue Jan 6 21:06:26 1998 +++ g10-0.2.0/g10/getkey.c Tue Jan 13 16:08:58 1998 @@ -51,6 +51,13 @@ PKT_public_cert *pkc; } *pkc_cache_entry_t; +typedef struct enum_seckey_context { + int eof; + STRLIST sl; + IOBUF iobuf; +} enum_seckey_context_t; + + static STRLIST keyrings; static STRLIST secret_keyrings; @@ -351,6 +358,9 @@ } + + + /**************** * scan the keyring and look for either the keyid or the name. */ @@ -581,6 +591,69 @@ iobuf_close(a); set_packet_list_mode(save_mode); return rc; +} + + +/**************** + * Enumerate all secret keys. Caller must use these procedure: + * 1) create a void pointer and initialize it to NULL + * 2) pass this void pointer by reference to this function + * and provide space for the secret key (pass a buffer for skc) + * 3) call this function as long as it does not return -1 + * to indicate EOF. + * 4) Always call this function a last time with SKC set to NULL, + * so that can free it's context. + * + * Return + */ +int +enum_secret_keys( void **context, PKT_secret_cert *skc ) +{ + int rc=0; + PACKET pkt; + int save_mode; + enum_seckey_context_t *c = *context; + + if( !c ) { /* make a new context */ + c = m_alloc_clear( sizeof *c ); + *context = c; + c->sl = secret_keyrings; + } + + if( !skc ) { /* free the context */ + m_free( c ); + *context = NULL; + return 0; + } + + if( c->eof ) + return -1; + + for( ; c->sl; c->sl = c->sl->next ) { + if( !c->iobuf ) { + if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) { + log_error("enum_secret_keys: can't open '%s'\n", c->sl->d ); + continue; /* try next file */ + } + } + + save_mode = set_packet_list_mode(0); + init_packet(&pkt); + while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) { + if( rc ) + ; /* e.g. unknown packet */ + else if( pkt.pkttype == PKT_SECRET_CERT ) { + copy_secret_cert( skc, pkt.pkt.secret_cert ); + set_packet_list_mode(save_mode); + return 0; /* found */ + } + free_packet(&pkt); + } + set_packet_list_mode(save_mode); + iobuf_close(c->iobuf); c->iobuf = NULL; + } + c->eof = 1; + return -1; } diff -urN g10-0.1.3/g10/import.c g10-0.2.0/g10/import.c --- g10-0.1.3/g10/import.c Thu Jan 1 01:00:00 1970 +++ g10-0.2.0/g10/import.c Mon Jan 19 17:53:09 1998 @@ -0,0 +1,55 @@ +/* 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 +#include +#include +#include +#include +#include + +#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 ) +{ + log_fatal("Not yet implemented"); + return 0; +} + + diff -urN g10-0.1.3/g10/keydb.h g10-0.2.0/g10/keydb.h --- g10-0.1.3/g10/keydb.h Tue Jan 6 21:06:10 1998 +++ g10-0.2.0/g10/keydb.h Wed Jan 14 16:18:14 1998 @@ -72,6 +72,17 @@ 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 ); @@ -97,6 +108,7 @@ int get_pubkey_byname( PKT_public_cert *pkc, const char *name ); int get_seckey( PKT_secret_cert *skc, u32 *keyid ); int get_seckey_byname( PKT_secret_cert *skc, const char *name, int unlock ); +int enum_secret_keys( void **context, PKT_secret_cert *skc ); char*get_user_id_string( u32 *keyid ); char*get_user_id( u32 *keyid, size_t *rn ); @@ -127,9 +139,9 @@ /*-- 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 ); diff -urN g10-0.1.3/g10/keygen.c g10-0.2.0/g10/keygen.c --- g10-0.1.3/g10/keygen.c Mon Jan 12 10:32:40 1998 +++ g10-0.2.0/g10/keygen.c Fri Jan 16 12:48:42 1998 @@ -113,7 +113,7 @@ 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 @@ break; } if( !node ) - log_bug(NULL); + BUG(); pkc = node->pkt->pkt.public_cert; /* and make the signature */ @@ -149,12 +149,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 ) diff -urN g10-0.1.3/g10/keyid.c g10-0.2.0/g10/keyid.c --- g10-0.1.3/g10/keyid.c Fri Jan 9 13:41:09 1998 +++ g10-0.2.0/g10/keyid.c Fri Jan 16 12:48:44 1998 @@ -106,7 +106,6 @@ 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; diff -urN g10-0.1.3/g10/main.h g10-0.2.0/g10/main.h --- g10-0.1.3/g10/main.h Fri Jan 9 13:38:57 1998 +++ g10-0.2.0/g10/main.h Fri Jan 16 17:47:39 1998 @@ -41,14 +41,14 @@ /*-- sign.c --*/ -int sign_file( const char *filename, int detached, STRLIST locusr, - int encrypt, STRLIST remusr ); +int sign_file( STRLIST filenames, int detached, STRLIST locusr, + int encrypt, STRLIST remusr, const char *outfile ); int sign_key( const char *username, STRLIST locusr ); 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); @@ -76,6 +76,9 @@ /*-- rsa.c --*/ 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*/ diff -urN g10-0.1.3/g10/mainproc.c g10-0.2.0/g10/mainproc.c --- g10-0.1.3/g10/mainproc.c Fri Jan 9 13:53:25 1998 +++ g10-0.2.0/g10/mainproc.c Fri Jan 16 12:48:43 1998 @@ -110,7 +110,6 @@ static int add_user_id( CTX c, PACKET *pkt ) { - u32 keyid[2]; KBNODE node, n1, n2; if( !c->cert ) { @@ -142,7 +141,6 @@ static int add_signature( CTX c, PACKET *pkt ) { - u32 keyid[2]; KBNODE node, n1, n2; if( !c->cert ) { @@ -329,7 +327,7 @@ 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 @@ 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 @@ { 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; diff -urN g10-0.1.3/g10/options.h g10-0.2.0/g10/options.h --- g10-0.1.3/g10/options.h Wed Jan 7 17:40:48 1998 +++ g10-0.2.0/g10/options.h Sun Jan 25 19:30:17 1998 @@ -39,9 +39,9 @@ int def_cipher_algo; int def_pubkey_algo; int def_digest_algo; - int reserved9; - int reserved10; - int reserved11; + int no_comment; + int marginals_needed; + int completes_needed; int reserved12; int reserved13; int reserved14; @@ -58,11 +58,13 @@ #define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ #define DBG_CACHE_VALUE 64 /* debug the cacheing */ #define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ +#define DBG_TRUST_VALUE 256 /* debug the trustdb */ #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) +#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) #endif /*G10_OPTIONS_H*/ diff -urN g10-0.1.3/g10/packet.h g10-0.2.0/g10/packet.h --- g10-0.1.3/g10/packet.h Fri Jan 9 13:39:12 1998 +++ g10-0.2.0/g10/packet.h Thu Jan 15 14:57:17 1998 @@ -42,9 +42,8 @@ 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 { 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,8 +96,11 @@ 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; + ulong local_id; /* internal use, valid if > 0 */ union { struct { MPI p; /* prime */ @@ -114,6 +117,8 @@ 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 { @@ -225,13 +230,16 @@ /*-- free-packet.c --*/ void free_pubkey_enc( PKT_pubkey_enc *enc ); void free_seckey_enc( PKT_signature *enc ); +void release_public_cert_parts( PKT_public_cert *cert ); void free_public_cert( PKT_public_cert *cert ); +void release_secret_cert_parts( PKT_secret_cert *cert ); void free_secret_cert( PKT_secret_cert *cert ); void free_user_id( PKT_user_id *uid ); void free_comment( PKT_comment *rem ); void free_packet( PACKET *pkt ); PKT_public_cert *copy_public_cert( PKT_public_cert *d, PKT_public_cert *s ); PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s ); +int cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc ); /*-- sig-check.c --*/ diff -urN g10-0.1.3/g10/parse-packet.c g10-0.2.0/g10/parse-packet.c --- g10-0.1.3/g10/parse-packet.c Fri Jan 9 13:41:33 1998 +++ g10-0.2.0/g10/parse-packet.c Fri Jan 16 12:48:45 1998 @@ -50,6 +50,7 @@ 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 @@ 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 @@ a += *p++; return a; } +#endif static unsigned short read_16(IOBUF inp) @@ -143,10 +145,11 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ PKT_onepass_sig *ops ) { int version; - unsigned n; if( pktlen < 13 ) { log_error("packet(%d) too short\n", pkttype); @@ -461,22 +524,27 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 diff -urN g10-0.1.3/g10/passphrase.c g10-0.2.0/g10/passphrase.c --- g10-0.1.3/g10/passphrase.c Fri Jan 9 13:42:04 1998 +++ g10-0.2.0/g10/passphrase.c Fri Jan 16 12:48:46 1998 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "util.h" #include "memory.h" diff -urN g10-0.1.3/g10/pkclist.c g10-0.2.0/g10/pkclist.c --- g10-0.1.3/g10/pkclist.c Fri Jan 9 13:50:09 1998 +++ g10-0.2.0/g10/pkclist.c Sat Jan 24 17:28:21 1998 @@ -32,6 +32,129 @@ #include "memory.h" #include "util.h" #include "trustdb.h" +#include "ttyio.h" + +/**************** + * Returns true if a ownertrust has changed. + */ +static int +query_ownertrust( ulong lid ) +{ + char *p; + int rc; + size_t n; + u32 keyid[2]; + PKT_public_cert *pkc ; + int changed=0; + + rc = keyid_from_trustdb( lid, keyid ); + if( rc ) { + log_error("ooops: can't get keyid for lid %lu\n", lid); + return 0; + } + + pkc = m_alloc_clear( sizeof *pkc ); + rc = get_pubkey( pkc, keyid ); + if( rc ) { + log_error("keyid %08lX: pubkey not found: %s\n", + (ulong)keyid[1], g10_errstr(rc) ); + return 0; + } + + tty_printf("No ownertrust defined for %lu:\n" + "%4u%c/%08lX %s \"", lid, + nbits_from_pkc( pkc ), pubkey_letter( pkc->pubkey_algo ), + (ulong)keyid[1], datestr_from_pkc( pkc ) ); + p = get_user_id( keyid, &n ); + tty_print_string( p, n ), + m_free(p); + tty_printf("\"\n\n" +"Please decide in how far do you trust this user to\n" +"correctly sign other users keys (looking at his passport,\n" +"checking the fingerprints from different sources ...)?\n\n" +" 1 = Don't know\n" +" 2 = I do NOT trust\n" +" 3 = I trust marginally\n" +" 4 = I trust fully\n" +" s = please show me more informations\n\n" ); + + for(;;) { + p = tty_get("Your decision? "); + trim_spaces(p); + tty_kill_prompt(); + if( *p && p[1] ) + ; + else if( *p == '?' ) { + tty_printf( +"It's up to you to assign a value here; this value will never be exported\n" +"to any 3rd party. We need it to implement the web-of-trust; it has nothing\n" +"to do with the (implicitly created) web-of-certificates.\n"); + } + else if( !p[1] && (*p >= '1' && *p <= '4') ) { + unsigned trust; + switch( *p ) { + case '1': trust = TRUST_UNDEFINED; break; + case '2': trust = TRUST_NEVER ; break; + case '3': trust = TRUST_MARGINAL ; break; + case '4': trust = TRUST_FULLY ; break; + default: BUG(); + } + if( !update_ownertrust( lid, trust ) ) + changed++; + break; + } + else if( *p == 's' || *p == 'S' ) { + tty_printf("You will see a list of signators etc. here\n"); + } + m_free(p); p = NULL; + } + m_free(p); + m_free(pkc); + return changed; +} + + +/**************** + * Try to add some more owner trusts (interactive) + * Returns: -1 if no ownertrust were added. + */ +static int +add_ownertrust( PKT_public_cert *pkc ) +{ + int rc; + void *context = NULL; + ulong lid; + unsigned trust; + int any=0; + + tty_printf( +"Could not find a valid trust path to the key. Lets see, wether we\n" +"can assign some missing owner trust values.\n\n"); + + rc = query_trust_record( pkc ); + if( rc ) { + log_error("Ooops: not in trustdb\n"); + return -1; + } + + lid = pkc->local_id; + while( !(rc=enum_trust_web( &context, &lid )) ) { + rc = get_ownertrust( lid, &trust ); + if( rc ) + log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid); + if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED || + trust == TRUST_UNKNOWN ) { + if( query_ownertrust( lid ) ) + any=1; + } + } + if( rc == -1 ) + rc = 0; + enum_trust_web( &context, NULL ); /* close */ + + + return rc? rc : any? 0:-1; +} /**************** @@ -41,6 +164,65 @@ static int do_we_trust( PKT_public_cert *pkc, int trustlevel ) { + int rc; + + switch( trustlevel ) { + case TRUST_UNKNOWN: /* 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) ); + return 0; /* no */ + } + rc = check_trust( pkc, &trustlevel ); + if( rc ) + log_fatal("trust check after insert failed: %s\n", + g10_errstr(rc) ); + if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED ) + BUG(); + return do_we_trust( pkc, trustlevel ); + + case TRUST_EXPIRED: + log_error("trust has expired: NOT yet implemented\n"); + return 0; /* no */ + + case TRUST_UNDEFINED: + if( opt.batch || opt.answer_no ) + log_info("no info to calculate a trust probability\n"); + else { + rc = add_ownertrust( pkc ); + if( !rc ) { + rc = check_trust( pkc, &trustlevel ); + if( rc ) + log_fatal("trust check after add_ownertrust failed: %s\n", + g10_errstr(rc) ); + /* FIXME: this is recursive; we better should unroll it */ + return do_we_trust( pkc, trustlevel ); + } + } + return 0; /* no */ + + case TRUST_NEVER: + log_info("We do NOT trust this key\n"); + return 0; /* no */ + + case TRUST_MARGINAL: + log_info("I'm not sure wether this keys really belongs to the owner\n" + "but I proceed anyway\n"); + return 1; /* yes */ + + case TRUST_FULLY: + log_info("This key probably belongs to the owner\n"); + return 1; /* yes */ + + case TRUST_ULTIMATE: + log_info("Our own keys is always good.\n"); + return 1; /* yes */ + + default: BUG(); + } + + /* Eventuell fragen falls der trustlevel nicht ausreichend ist */ @@ -65,7 +247,6 @@ 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!!! */ @@ -83,13 +264,14 @@ else if( !(rc=check_pubkey_algo(pkc->pubkey_algo)) ) { int trustlevel; - rc = check_pkc_trust( pkc, &trustlevel ); + rc = check_trust( pkc, &trustlevel ); if( rc ) { free_public_cert( pkc ); pkc = NULL; log_error("error checking pkc of '%s': %s\n", remusr->d, g10_errstr(rc) ); } else if( do_we_trust( pkc, trustlevel ) ) { + /* note: do_we_trust may have changed the trustlevel */ PKC_LIST r; r = m_alloc( sizeof *r ); diff -urN g10-0.1.3/g10/ringedit.c g10-0.2.0/g10/ringedit.c --- g10-0.1.3/g10/ringedit.c Tue Jan 6 21:12:54 1998 +++ g10-0.2.0/g10/ringedit.c Fri Jan 16 12:48:42 1998 @@ -68,7 +68,12 @@ 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 @@ 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 @@ * * 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 @@ * 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 @@ 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 @@ * 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 @@ 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 @@ * 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 @@ unlock_keyblock( KBPOS *kbpos ) { if( !check_pos(kbpos) ) - log_bug(NULL); + BUG(); } /**************** @@ -389,13 +423,75 @@ 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 @@ { RESTBL *rentry; IOBUF fp; - KBNODE kbctx, node; int rc; u32 len; int ctb; @@ -588,7 +683,7 @@ /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/ if( len < 2 ) - log_bug(NULL); + BUG(); if( len < 256 ) { ctb = 0x80; diff -urN g10-0.1.3/g10/seckey-cert.c g10-0.2.0/g10/seckey-cert.c --- g10-0.1.3/g10/seckey-cert.c Tue Jan 6 21:24:47 1998 +++ g10-0.2.0/g10/seckey-cert.c Fri Jan 16 12:48:47 1998 @@ -60,7 +60,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 ); diff -urN g10-0.1.3/g10/seskey.c g10-0.2.0/g10/seskey.c --- g10-0.1.3/g10/seskey.c Fri Jan 9 13:33:22 1998 +++ g10-0.2.0/g10/seskey.c Fri Jan 16 12:47:22 1998 @@ -46,7 +46,7 @@ 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 @@ { 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 @@ { 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 @@ { 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 @@ case DIGEST_ALGO_SHA1: return encode_sha1_value( md_read(md, DIGEST_ALGO_SHA1), 20, nbits ); default: - log_bug(NULL); + BUG(); } } diff -urN g10-0.1.3/g10/sig-check.c g10-0.2.0/g10/sig-check.c --- g10-0.1.3/g10/sig-check.c Fri Jan 9 13:53:28 1998 +++ g10-0.2.0/g10/sig-check.c Fri Jan 16 17:54:05 1998 @@ -143,7 +143,7 @@ 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 @@ 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 @@ * 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 @@ 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 @@ 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 ); diff -urN g10-0.1.3/g10/sign.c g10-0.2.0/g10/sign.c --- g10-0.1.3/g10/sign.c Fri Jan 9 13:37:56 1998 +++ g10-0.2.0/g10/sign.c Fri Jan 16 17:47:59 1998 @@ -52,7 +52,7 @@ 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? */ @@ -64,17 +64,22 @@ /**************** - * Sign the file with name FILENAME. If DETACHED has the value true, - * make a detached signature. If FILENAME is NULL read from stdin + * Sign the files whose names are in FILENAME. + * If DETACHED has the value true, + * make a detached signature. If FILENAMES->d is NULL read from stdin * and ignore the detached mode. Sign the file with all secret keys * which can be taken from LOCUSR, if this is NULL, use the default one * If ENCRYPT is true, use REMUSER (or ask if it is NULL) to encrypt the * signed data for these users. + * If OUTFILE is not NULL; this file is used for output and the function + * does not ask for overwrite permission; output is then always + * uncompressed, non-armored and in binary mode. */ int -sign_file( const char *filename, int detached, STRLIST locusr, - int encrypt, STRLIST remusr ) +sign_file( STRLIST filenames, int detached, STRLIST locusr, + int encrypt, STRLIST remusr, const char *outfile ) { + const char *fname; armor_filter_context_t afx; compress_filter_context_t zfx; md_filter_context_t mfx; @@ -84,10 +89,11 @@ 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; + int multifile = 0; memset( &afx, 0, sizeof afx); memset( &zfx, 0, sizeof zfx); @@ -96,6 +102,16 @@ memset( &efx, 0, sizeof efx); init_packet( &pkt ); + if( filenames ) { + fname = filenames->d; + multifile = !!filenames->next; + } + else + fname = NULL; + + if( fname && filenames->next && (!detached || encrypt) ) + log_bug("multiple files can only be detached signed"); + if( (rc=build_skc_list( locusr, &skc_list, 1 )) ) goto leave; if( encrypt ) { @@ -104,28 +120,40 @@ } /* prepare iobufs */ - if( !(inp = iobuf_open(filename)) ) { - log_error("can't open %s: %s\n", filename? filename: "[stdin]", + if( multifile ) /* have list of filenames */ + inp = NULL; /* we do it later */ + else if( !(inp = iobuf_open(fname)) ) { + log_error("can't open %s: %s\n", fname? fname: "[stdin]", strerror(errno) ); rc = G10ERR_OPEN_FILE; goto leave; } - if( !(out = open_outfile( filename, opt.armor? 1: detached? 2:0 )) ) { + if( outfile ) { + if( !(out = iobuf_create( outfile )) ) { + log_error("can't create %s: %s\n", outfile, strerror(errno) ); + rc = G10ERR_CREATE_FILE; + goto leave; + } + else if( opt.verbose ) + log_info("writing to '%s'\n", outfile ); + } + else if( !(out = open_outfile( fname, opt.armor? 1: detached? 2:0 )) ) { rc = G10ERR_CREATE_FILE; goto leave; } /* prepare to calculate the MD over the input */ - if( opt.textmode && opt.armor ) + if( opt.textmode && opt.armor && !outfile ) iobuf_push_filter( inp, text_filter, &tfx ); mfx.md = md_open(DIGEST_ALGO_RMD160, 0); - iobuf_push_filter( inp, md_filter, &mfx ); + if( !multifile ) + iobuf_push_filter( inp, md_filter, &mfx ); - if( opt.armor ) + if( opt.armor && !outfile ) iobuf_push_filter( out, armor_filter, &afx ); write_comment( out, "#Created by G10 pre-release " VERSION ); - if( opt.compress ) + if( opt.compress && !outfile ) iobuf_push_filter( out, compress_filter, &zfx ); if( encrypt ) { @@ -141,7 +169,7 @@ skc = skc_rover->skc; ops = m_alloc_clear( sizeof *ops ); - ops->sig_class = opt.textmode? 0x01 : 0x00; + ops->sig_class = opt.textmode && !outfile ? 0x01 : 0x00; ops->digest_algo = DIGEST_ALGO_RMD160; ops->pubkey_algo = skc->pubkey_algo; keyid_from_skc( skc, ops->keyid ); @@ -161,17 +189,40 @@ /* setup the inner packet */ if( detached ) { - /* read, so that the filter can calculate the digest */ - while( iobuf_get(inp) != -1 ) - ; + if( multifile ) { + STRLIST sl = filenames; + + if( opt.verbose ) + log_info("signing:" ); + for(; sl; sl = sl->next ) { + if( !(inp = iobuf_open(sl->d)) ) { + log_error("can't open %s: %s\n", sl->d, strerror(errno) ); + rc = G10ERR_OPEN_FILE; + goto leave; + } + if( opt.verbose ) + fprintf(stderr, " '%s'", sl->d ); + iobuf_push_filter( inp, md_filter, &mfx ); + while( iobuf_get(inp) != -1 ) + ; + iobuf_close(inp); inp = NULL; + } + if( opt.verbose ) + putc( '\n', stderr ); + } + else { + /* read, so that the filter can calculate the digest */ + while( iobuf_get(inp) != -1 ) + ; + } } else { - if( filename ) { - pt = m_alloc( sizeof *pt + strlen(filename) - 1 ); - pt->namelen = strlen(filename); - memcpy(pt->name, filename, pt->namelen ); + if( fname ) { + pt = m_alloc( sizeof *pt + strlen(fname) - 1 ); + pt->namelen = strlen(fname); + memcpy(pt->name, fname, pt->namelen ); if( !(filesize = iobuf_get_filelength(inp)) ) - log_info("warning: '%s' is an empty file\n", filename ); + log_info("warning: '%s' is an empty file\n", fname ); } else { /* no filename */ pt = m_alloc( sizeof *pt - 1 ); @@ -179,7 +230,7 @@ filesize = 0; /* stdin */ } pt->timestamp = make_timestamp(); - pt->mode = opt.textmode? 't':'b'; + pt->mode = opt.textmode && !outfile ? 't':'b'; pt->len = filesize; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; @@ -203,7 +254,7 @@ sig = m_alloc_clear( sizeof *sig ); sig->pubkey_algo = skc->pubkey_algo; sig->timestamp = make_timestamp(); - sig->sig_class = opt.textmode? 0x01 : 0x00; + sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00; md = md_copy( mfx.md ); md_putc( md, sig->sig_class ); @@ -267,7 +318,7 @@ } #endif/*HAVE_RSA_CIPHER*/ else - log_bug(NULL); + BUG(); md_close( md ); @@ -377,7 +428,7 @@ 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; @@ -427,7 +478,6 @@ && 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 */ @@ -495,14 +545,13 @@ 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; @@ -636,12 +685,10 @@ 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; @@ -704,13 +751,12 @@ 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; diff -urN g10-0.1.3/g10/skclist.c g10-0.2.0/g10/skclist.c --- g10-0.1.3/g10/skclist.c Fri Jan 9 13:50:51 1998 +++ g10-0.2.0/g10/skclist.c Fri Jan 16 12:38:11 1998 @@ -49,7 +49,6 @@ 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 */ diff -urN g10-0.1.3/g10/trustdb.c g10-0.2.0/g10/trustdb.c --- g10-0.1.3/g10/trustdb.c Fri Jan 9 09:05:27 1998 +++ g10-0.2.0/g10/trustdb.c Sun Jan 25 19:32:51 1998 @@ -25,6 +25,7 @@ #include #include #include +#include #include "errors.h" #include "iobuf.h" @@ -33,39 +34,44 @@ #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; byte reserved; union { - byte raw[TRUST_RECORD_LEN-2]; struct { /* version 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; + byte no_sigs; + /* fixme: indicate a flag to */ } pubkey; struct { /* cache record */ - u32 local_id; - u32 keyid[2]; + ulong owner; + u32 keyid[2]; /* needed?? */ byte valid; byte reserved; byte blockhash[20]; @@ -74,12 +80,109 @@ byte n_fully; byte trustlevel; } cache; + struct { + ulong owner; /* local_id of record owner (pubkey record) */ + ulong chain; /* offset of next record or NULL for last one */ + struct { + ulong local_id; /* of pubkey record of signator (0=unused) */ + byte flag; /* reserved */ + } sig[SIGS_PER_RECORD]; + } sigrec; } r; }; +typedef struct trust_record TRUSTREC; +typedef struct { + ulong pubkey_id; /* localid of the pubkey */ + ulong sig_id; /* returned signature id */ + unsigned sig_flag; /* returned signature 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; +}; + + +typedef struct trust_info TRUST_INFO; +struct trust_info { + ulong lid; + unsigned trust; +}; + + +typedef struct trust_seg_list *TRUST_SEG_LIST; +struct trust_seg_list { + TRUST_SEG_LIST next; + int nseg; /* number of segmens */ + int dup; + TRUST_INFO seg[1]; /* segment list */ +}; +typedef struct { + TRUST_SEG_LIST tsl; + int index; +} ENUM_TRUST_WEB_CONTEXT; + + +static void create_db( const char *fname ); +static void open_db(void); +static int read_record( ulong recnum, TRUSTREC *rec ); +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, int create ); + +static LOCAL_ID_INFO *new_lid_table(void); +static void release_lid_table( LOCAL_ID_INFO *tbl ); +static int ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); +static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag ); +static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); + +static void print_user_id( const char *text, u32 *keyid ); +static int do_list_path( TRUST_INFO *stack, int depth, int max_depth, + LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ); + +static int list_sigs( ulong pubkey_id ); +static int build_sigrecs( ulong pubkeyid, int kludge ); +static int propagate_trust( TRUST_SEG_LIST tslist ); +static int do_check( ulong pubkeyid, unsigned *trustlevel ); + +static int update_no_sigs( ulong lid, int no_sigs ); + static char *db_name; +static int db_fd = -1; +/* a table used to keep track of ultimately trusted keys + * which are the ones from our secrings */ +static LOCAL_ID_INFO *ultikey_table; + +static ulong last_trust_web_key; +static TRUST_SEG_LIST last_trust_web_tslist; + +#define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ + (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3))) +#define buftoushort( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1))) +#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 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) ) + /************************************************** ************** read and write helpers ************ @@ -92,25 +195,18 @@ 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-- ) @@ -131,8 +227,6 @@ create_db( const char *fname ) { FILE *fp; - u32 along; - u16 ashort; fp =fopen( fname, "w" ); if( !fp ) @@ -147,7 +241,7 @@ fwrite_32( fp, make_timestamp() ); /* created */ fwrite_32( fp, 0 ); /* not yet modified */ fwrite_32( fp, 0 ); /* not yet validated*/ - fwrite_32( fp, 0 ); /* local-id-counter */ + fwrite_32( fp, 0 ); /* local-id-counter (not used) */ fwrite_8( fp, 3 ); /* marginals needed */ fwrite_8( fp, 1 ); /* completes needed */ fwrite_8( fp, 4 ); /* max_cet_depth */ @@ -155,24 +249,1269 @@ fclose(fp); } +static void +open_db() +{ + TRUSTREC rec; + assert( db_fd == -1 ); + db_fd = open( db_name, O_RDWR ); + if( db_fd == -1 ) + log_fatal("can't open %s: %s\n", db_name, strerror(errno) ); + if( read_record( 0, &rec ) ) + log_fatal("TrustDB %s is invalid\n", db_name ); + /* fixme: check ->locked and other stuff */ +} + + +/**************** + * read the record with number recnum + * returns: -1 on error, 0 on success + */ +static int +read_record( ulong recnum, TRUSTREC *rec ) +{ + byte buf[TRUST_RECORD_LEN], *p; + int rc = 0; + int n, i; + + if( db_fd == -1 ) + open_db(); + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error("trustdb: lseek failed: %s\n", strerror(errno) ); + return G10ERR_READ_FILE; + } + n = read( db_fd, buf, TRUST_RECORD_LEN); + if( !n ) { + return -1; /* eof */ + } + else if( n != TRUST_RECORD_LEN ) { + log_error("trustdb: read failed (n=%d): %s\n", n, strerror(errno) ); + return G10ERR_READ_FILE; + } + p = buf; + rec->rectype = *p++; + rec->reserved = *p++; + switch( rec->rectype ) { + case 0: /* unused record */ + break; + case 1: /* version record */ + rec->r.version.magic[0] = *p++; + rec->r.version.magic[1] = *p++; + rec->r.version.version = *p++; + memcpy( rec->r.version.reserved, p, 3); p += 3; + 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++; + if( recnum ) { + log_error("%s: version record with recnum %lu\n", + db_name, (ulong)recnum ); + rc = G10ERR_TRUSTDB; + } + if( rec->reserved != 'g' || rec->r.version.magic[0] != '1' + || rec->r.version.magic[1] != '0' ) { + log_error("%s: not a trustdb file\n", db_name ); + rc = G10ERR_TRUSTDB; + } + if( rec->r.version.version != 1 ) { + log_error("%s: invalid file version %d\n", + db_name, rec->r.version.version ); + rc = G10ERR_TRUSTDB; + } + break; + case 2: + 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.pubkey_algo = *p++; + rec->r.pubkey.reserved = *p++; + memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20; + rec->r.pubkey.ownertrust = *p++; + rec->r.pubkey.no_sigs = *p++; + if( rec->r.pubkey.local_id != recnum ) { + log_error("%s: pubkey local_id != recnum (%lu,%lu)\n", + db_name, + (ulong)rec->r.pubkey.local_id, + (ulong)recnum ); + rc = G10ERR_TRUSTDB; + } + break; + case 3: + 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++; + rec->r.cache.reserved = *p++; + memcpy(rec->r.cache.blockhash, p, 20); p += 20; + rec->r.cache.n_untrusted = *p++; + rec->r.cache.n_marginal = *p++; + rec->r.cache.n_fully = *p++; + rec->r.cache.trustlevel = *p++; + break; + case 4: + case 5: + 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 = buftoulong(p); p += 4; + rec->r.sigrec.sig[i].flag = *p++; + } + break; + default: + log_error("%s: invalid record type %d at recnum %lu\n", + db_name, rec->rectype, (ulong)recnum ); + rc = G10ERR_TRUSTDB; + break; + } + return rc; +} +/**************** + * Write the record at RECNUM + */ +static int +write_record( ulong recnum, TRUSTREC *rec ) +{ + byte buf[TRUST_RECORD_LEN], *p; + int rc = 0; + int i, n; + + if( db_fd == -1 ) + open_db(); + + memset(buf, 0, TRUST_RECORD_LEN); + p = buf; + *p++ = rec->rectype; + *p++ = rec->reserved; + switch( rec->rectype ) { + case 0: /* unused record */ + break; + case 1: /* version record */ + BUG(); + break; + case 2: + 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.pubkey_algo; + *p++ = rec->r.pubkey.reserved; + memcpy( p, rec->r.pubkey.fingerprint, 20); p += 20; + *p++ = rec->r.pubkey.ownertrust; + *p++ = rec->r.pubkey.no_sigs; + assert( rec->r.pubkey.local_id == recnum ); + break; + case 3: + 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; + *p++ = rec->r.cache.reserved; + memcpy(p, rec->r.cache.blockhash, 20); p += 20; + *p++ = rec->r.cache.n_untrusted; + *p++ = rec->r.cache.n_marginal; + *p++ = rec->r.cache.n_fully; + *p++ = rec->r.cache.trustlevel; + break; + case 4: + case 5: + ulongtobuf(p, rec->r.sigrec.owner); p += 4; + ulongtobuf(p, rec->r.sigrec.chain); p += 4; + for(i=0; i < SIGS_PER_RECORD; i++ ) { + ulongtobuf(p, rec->r.sigrec.sig[i].local_id); p += 4; + *p++ = rec->r.sigrec.sig[i].flag; + } + break; + default: + BUG(); + } + if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) { + log_error("trustdb: lseek failed: %s\n", strerror(errno) ); + return G10ERR_WRITE_FILE; + } + n = write( db_fd, buf, TRUST_RECORD_LEN); + if( n != TRUST_RECORD_LEN ) { + log_error("trustdb: write failed (n=%d): %s\n", n, strerror(errno) ); + return G10ERR_WRITE_FILE; + } + return rc; +} +/**************** + * create a new record and return its record number + */ +static ulong +new_recnum() +{ + off_t offset; + ulong recnum; + TRUSTREC rec; + int rc; + + /* fixme: look for unused records */ + offset = lseek( db_fd, 0, SEEK_END ); + if( offset == -1 ) + 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 ; +} +/**************** + * Scan the trustdb for a record of type RECTYPE which matches PKC + * The local_id is set to the correct value + */ +static int +scan_record_by_pkc( PKT_public_cert *pkc, TRUSTREC *rec, int rectype ) +{ + ulong recnum; + u32 keyid[2]; + byte *fingerprint; + size_t fingerlen; + int rc; + + assert( rectype == 2 || rectype == 3 ); + + keyid_from_pkc( pkc, keyid ); + fingerprint = fingerprint_from_pkc( pkc, &fingerlen ); + assert( fingerlen == 20 || fingerlen == 16 ); + + for(recnum=1; !(rc=read_record( recnum, rec)); recnum++ ) { + if( rec->rectype != rectype ) + continue; + if( rec->rectype == 2 ) { + if( rec->r.pubkey.keyid[0] == keyid[0] + && rec->r.pubkey.keyid[1] == keyid[1] + && rec->r.pubkey.pubkey_algo == pkc->pubkey_algo + && !memcmp(rec->r.pubkey.fingerprint, fingerprint, fingerlen) + ) { /* found */ + /* store the local_id */ + if( pkc->local_id && pkc->local_id != recnum ) + log_error("%s: found record, but local_id from mem does " + "not match recnum (%lu,%lu)\n", db_name, + (ulong)pkc->local_id, (ulong)recnum ); + pkc->local_id = recnum; + return 0; + } + } + else + log_bug("not yet implemented\n"); + } + if( rc != -1 ) + log_error("%s: scan_record_by_pkc failed: %s\n",db_name, g10_errstr(rc) ); + return rc; +} + +/**************** + * scan the DB for a record of type RECTYPE which can be localized + * with LOCAL_ID + */ +static int +scan_record( ulong local_id, TRUSTREC *rec, int rectype, ulong *r_recnum ) +{ + ulong recnum; + int rc; + + assert( rectype == 3 || rectype == 4 ); + + for(recnum=1; !(rc=read_record( recnum, rec)); recnum++ ) { + if( rec->rectype != rectype ) + continue; + if( rec->rectype == 34 ) { + if( rec->r.cache.owner == local_id ) { /* found */ + *r_recnum = recnum; + return 0; + } + } + else if( rec->rectype == 4 ) { + if( rec->r.sigrec.owner == local_id ) { /* found */ + *r_recnum = recnum; + return 0; + } + } + else + log_bug("not yet implemented\n"); + } + if( rc != -1 ) + log_error("%s: scan_record failed: %s\n",db_name, g10_errstr(rc) ); + return rc; +} + + +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%s\n", + rec->r.pubkey.keyid[1], rec->r.pubkey.ownertrust, + rec->r.pubkey.no_sigs?" (inv sigs)":""); + break; + case 3: fprintf(fp, "cache\n"); + case 4: + 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'); + for(recnum=0; !read_record( recnum, &rec); recnum++ ) + dump_record( recnum, &rec, stdout ); + } +} + +void +list_trust_path( int max_depth, const char *username ) +{ + int rc; + int wipe=0; + int i; + TRUSTREC rec; + PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); + + if( max_depth < 0 ) { + wipe = 1; + max_depth = -max_depth; + } + + if( (rc = get_pubkey_byname( pkc, username )) ) + log_error("user '%s' not found: %s\n", username, g10_errstr(rc) ); + 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_info("user '%s' not in trustdb - inserting\n", username); + rc = insert_trust_record( pkc ); + if( rc ) + log_error("failed to put '%s' into trustdb: %s\n", username, g10_errstr(rc)); + else { + assert( pkc->local_id ); + } + } + + if( !rc ) { + TRUST_SEG_LIST tsl, tslist = NULL; + + if( !qry_lid_table_flag( ultikey_table, pkc->local_id, NULL ) ) { + tslist = m_alloc( sizeof *tslist ); + tslist->nseg = 1; + tslist->dup = 0; + tslist->seg[0].lid = pkc->local_id; + tslist->seg[0].trust = 0; + tslist->next = NULL; + rc = 0; + } + else { + LOCAL_ID_INFO *lids = new_lid_table(); + TRUST_INFO stack[MAX_LIST_SIGS_DEPTH]; + + stack[0].lid = pkc->local_id; + stack[0].trust = 0; + rc = do_list_path( stack, 1, max_depth, lids, &tslist ); + if( wipe ) { /* wipe out duplicates */ + LOCAL_ID_INFO *work; + + work = new_lid_table(); + for( tsl=tslist; tsl; tsl = tsl->next ) { + for(i=1; i < tsl->nseg-1; i++ ) { + if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) { + tsl->dup = 1; /* mark as duplicate */ + break; + } + } + } + release_lid_table(work); + } + release_lid_table(lids); + } + if( rc ) + log_error("user '%s' list problem: %s\n", username, g10_errstr(rc)); + rc = propagate_trust( tslist ); + if( rc ) + log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc)); + for(tsl = tslist; tsl; tsl = tsl->next ) { + int i; + + if( tsl->dup ) + continue; + printf("trust path:" ); + for(i=0; i < tsl->nseg; i++ ) + printf(" %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust ); + putchar('\n'); + } + } + 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 create ) +{ + 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 && create ) { /* no signature records */ + rc = build_sigrecs( c->pubkey_id, 1 ); + if( rc ) { + if( rc != -1 ) + log_info("%lu: error building sigs on the fly: %s\n", + c->pubkey_id, g10_errstr(rc) ); + rc = -1; + } + else /* once more */ + rc = scan_record( c->pubkey_id, r, 4, &rnum ); + } + if( rc == -1 ) { /* no signature records */ + c->ctl.eof = 1; + return -1; /* return eof */ + } + 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 +ins_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 +qry_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 void +upd_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 ) { + a->flag = flag; + return; + } + BUG(); +} + + + + +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. + */ +static int +verify_own_certs() +{ + int rc; + void *enum_context = NULL; + PKT_secret_cert *skc = m_alloc_clear( sizeof *skc ); + PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc ); + u32 keyid[2]; + + while( !(rc=enum_secret_keys( &enum_context, skc) ) ) { + /* 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 + * and verify this signature during + * startup + */ + + keyid_from_skc( skc, keyid ); + + if( DBG_TRUST ) + log_debug("checking secret key %08lX\n", (ulong)keyid[1] ); + + /* look wether we can access the public key of this secret key */ + rc = get_pubkey( pkc, keyid ); + if( rc ) { + log_error("keyid %08lX: secret key without public key\n", + (ulong)keyid[1] ); + goto leave; + } + if( cmp_public_secret_cert( pkc, skc ) ) { + log_error("keyid %08lX: secret and public key don't match\n", + (ulong)keyid[1] ); + rc = G10ERR_GENERAL; + goto leave; + } + + /* make sure that the pubkey is in the trustdb */ + rc = query_trust_record( pkc ); + if( rc == -1 ) { /* put it into the trustdb */ + rc = insert_trust_record( pkc ); + if( rc ) { + log_error("keyid %08lX: can't put it into the trustdb\n", + (ulong)keyid[1] ); + goto leave; + } + } + else if( rc ) { + log_error("keyid %08lX: query record failed\n", (ulong)keyid[1] ); + goto leave; + + } + + if( DBG_TRUST ) + log_debug("putting %08lX(%lu) into ultikey_table\n", + (ulong)keyid[1], pkc->local_id ); + if( ins_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 ); + release_public_cert_parts( pkc ); + } + if( rc != -1 ) + log_error("enum_secret_keys failed: %s\n", g10_errstr(rc) ); + else + rc = 0; + + leave: + free_secret_cert( skc ); + free_public_cert( pkc ); + 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, 0 ); + 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( !qry_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( ins_lid_table_item( lids, sx.sig_id, *lineno ) ) { + unsigned refline; + qry_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( TRUST_INFO *stack, int depth, int max_depth, + LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ) +{ + SIGREC_CONTEXT sx; + unsigned last_depth; + int rc; + + assert(depth); + + /*printf("%2lu/%d: scrutinizig\n", stack[depth-1], depth);*/ + if( depth >= max_depth || depth >= MAX_LIST_SIGS_DEPTH-1 ) { + /*printf("%2lu/%d: to deeply nested\n", stack[depth-1], depth);*/ + return 0; + } + memset( &sx, 0, sizeof sx ); + sx.pubkey_id = stack[depth-1].lid; + /* loop over all signatures. If we do not have any, try to + * create them */ + while( !(rc = walk_sigrecs( &sx, 1 )) ) { + TRUST_SEG_LIST tsl, t2, tl; + int i; + + stack[depth].lid = sx.sig_id; + stack[depth].trust = 0; + if( qry_lid_table_flag( lids, sx.sig_id, &last_depth) ) { + /*printf("%2lu/%d: marked\n", sx.sig_id, depth );*/ + ins_lid_table_item( lids, sx.sig_id, depth); + last_depth = depth; + } + else if( depth < last_depth ) { + /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_id, depth, last_depth);*/ + last_depth = depth; + upd_lid_table_flag( lids, sx.sig_id, depth); + } + + if( last_depth < depth ) + /*printf("%2lu/%d: already visited\n", sx.sig_id, depth)*/; + else if( !qry_lid_table_flag( ultikey_table, sx.sig_id, NULL ) ) { + /* found end of path; store it, ordered by path length */ + tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) ); + tsl->nseg = depth+1; + tsl->dup = 0; + for(i=0; i <= depth; i++ ) + tsl->seg[i] = stack[i]; + for(t2=*tslist,tl=NULL; t2; tl=t2, t2 = t2->next ) + if( depth < t2->nseg ) + break; + if( !tl ) { + tsl->next = t2; + *tslist = tsl; + } + else { + tsl->next = t2; + tl->next = tsl; + } + /*putchar('.'); fflush(stdout);*/ + /*printf("%2lu/%d: found\n", sx.sig_id, depth);*/ + } + else { + rc = do_list_path( stack, depth+1, max_depth, lids, tslist); + if( rc && rc != -1 ) + break; + } + } + return rc==-1? 0 : rc; +} + + + +/**************** + * Check all the sigs of the given keyblock and mark them + * as checked. + */ +static int +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 ) { + 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", + (ulong)node->pkt->pkt.signature->keyid[1], + g10_errstr(rc) ); + } + } + return 0; +} + +/**************** + * If we do not have sigrecs for the given key, build them and write them + * to the trustdb + */ +static int +build_sigrecs( ulong pubkeyid, int kludge ) +{ + 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; + } + if( kludge && rec.r.pubkey.no_sigs ) { + rc = -1; + goto leave; + } + finfo = m_alloc_clear( sizeof *finfo ); + finfo->keyid[0] = rec.r.pubkey.keyid[0]; + finfo->keyid[1] = rec.r.pubkey.keyid[1]; + 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" ); + update_no_sigs( pubkeyid, 1 ); + rc = G10ERR_BAD_CERT; + goto leave; + } + update_no_sigs( pubkeyid, 0 ); + /* valid key signatures are now marked; we can now build the + * sigrecs */ + memset( &rec, 0, sizeof rec ); + 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 errors of the trustdb or a + * remove operation on the pubkey database - which should + * not disturb us, because we have to chace them anyway. */ + rc = set_signature_packets_local_id( node->pkt->pkt.signature ); + if( rc ) + log_fatal("set_signature_packets_local_id failed: %s\n", + 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; +} + +/**************** + * Make a list of trust paths + */ +static int +make_tsl( ulong pubkey_id, TRUST_SEG_LIST *ret_tslist ) +{ + int i, rc; + LOCAL_ID_INFO *lids = new_lid_table(); + TRUST_INFO stack[MAX_LIST_SIGS_DEPTH]; + TRUST_SEG_LIST tsl, tslist; + int max_depth = 4; + + tslist = *ret_tslist = NULL; + + if( !qry_lid_table_flag( ultikey_table, pubkey_id, NULL ) ) { + tslist = m_alloc( sizeof *tslist ); + tslist->nseg = 1; + tslist->dup = 0; + tslist->seg[0].lid = pubkey_id; + tslist->seg[0].trust = 0; + tslist->next = NULL; + rc = 0; + } + else { + stack[0].lid = pubkey_id; + stack[0].trust = 0; + rc = do_list_path( stack, 1, max_depth, lids, &tslist ); + } + if( !rc ) { /* wipe out duplicates */ + LOCAL_ID_INFO *work = new_lid_table(); + for( tsl=tslist; tsl; tsl = tsl->next ) { + for(i=1; i < tsl->nseg-1; i++ ) { + if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) { + tsl->dup = 1; /* mark as duplicate */ + break; + } + } + } + release_lid_table(work); + *ret_tslist = tslist; + } + else + ; /* FIXME: release tslist */ + release_lid_table(lids); + return rc; +} + + +/**************** + * Given a trust segment list tslist, walk over all paths and fill in + * the trust information for each segment. What this function does is + * to assign a trustvalue to the first segment (which is the requested key) + * of each path. + * + * FIXME: We have to do more thinks here. e.g. we should never increase + * the trust value. + * + * Do not do it for duplicates. + */ +static int +propagate_trust( TRUST_SEG_LIST tslist ) +{ + int i, rc; + unsigned trust; + TRUST_SEG_LIST tsl; + + for(tsl = tslist; tsl; tsl = tsl->next ) { + if( tsl->dup ) + continue; + assert( tsl->nseg ); + /* the last segment is always a ultimately trusted one, so we can + * assign a fully trust to the next one */ + i = tsl->nseg-1; + tsl->seg[i].trust = TRUST_ULTIMATE; + trust = TRUST_FULLY; + for(i-- ; i >= 0; i-- ) { + tsl->seg[i].trust = trust; + if( i > 0 ) { + /* get the trust of this pubkey */ + rc = get_ownertrust( tsl->seg[i].lid, &trust ); + if( rc ) + return rc; + } + } + } + return 0; +} + + +/**************** + * we have the pubkey record but nothing more is known + */ +static int +do_check( ulong pubkeyid, unsigned *trustlevel ) +{ + int i, rc=0; + ulong rnum; + TRUSTREC rec; + TRUST_SEG_LIST tsl, tsl2, tslist; + int marginal, fully; + int fully_needed = opt.completes_needed; + int marginal_needed = opt.marginals_needed; + + assert( fully_needed > 0 && marginal_needed > 1 ); + + + *trustlevel = TRUST_UNDEFINED; + + /* 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, 1 ); + if( !rc ) /* and read again */ + rc = scan_record( pubkeyid, &rec, 4, &rnum ); + } + if( rc ) + return rc; /* error while looking for sigrec or building sigrecs */ + + /* fixme: take it from the cache if it is valid */ + + /* Make a list of all possible trust-paths */ + rc = make_tsl( pubkeyid, &tslist ); + if( rc ) + return rc; + rc = propagate_trust( tslist ); + if( rc ) + return rc; + for(tsl = tslist; tsl; tsl = tsl->next ) { + if( tsl->dup ) + continue; + + log_debug("tslist segs:" ); + for(i=0; i < tsl->nseg; i++ ) + fprintf(stderr, " %lu/%02x", tsl->seg[i].lid, tsl->seg[i].trust ); + putc('\n',stderr); + } + + /* and look wether there is a trusted path. + * We only have to look at the first segment, because + * propagate_trust has investigated all other segments */ + marginal = fully = 0; + for(tsl = tslist; tsl; tsl = tsl->next ) { + if( tsl->dup ) + continue; + if( tsl->seg[0].trust == TRUST_ULTIMATE ) { + *trustlevel = TRUST_ULTIMATE; /* our own key */ + break; + } + if( tsl->seg[0].trust == TRUST_FULLY ) { + marginal++; + fully++; + } + else if( tsl->seg[0].trust == TRUST_MARGINAL ) + marginal++; + + if( fully >= fully_needed ) { + *trustlevel = TRUST_FULLY; + break; + } + } + if( !tsl && marginal >= marginal_needed ) + *trustlevel = TRUST_MARGINAL; + + /* cache the tslist */ + if( last_trust_web_key ) { + for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) { + tsl2 = tsl->next; + m_free(tsl); + } + } + last_trust_web_key = pubkeyid; + last_trust_web_tslist = tslist; + return 0; +} /********************************************************* @@ -181,32 +1520,51 @@ /**************** * Perform some checks over the trustdb - * level 0: used on initial program startup + * level 0: only open the db + * 1: used for initial program startup */ int -check_trustdb( int level ) +init_trustdb( int level ) { - if( !level ) { - char *fname = make_filename("~/.g10", "trustDB", NULL ); + int rc=0; + + 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 - */ + * in ~/.g10/ here */ + rc = verify_private_data(); + if( !rc ) { + /* verify, that our own certificates are in the trustDB + * or move them to the trustdb. */ + rc = verify_own_certs(); + + /* should we check wether there is no other ultimately trusted + * key in the database? */ + + } } else - log_bug(NULL); + BUG(); - return 0; + return rc; } @@ -220,7 +1578,7 @@ * found: * Do we have a valid cache record for it? * yes: return trustlevel from cache - * no: make a cache record + * no: make a cache record and all the other stuff * not found: * Return with a trustlevel, saying that we do not have * a trust record for it. The caller may use insert_trust_record() @@ -232,14 +1590,306 @@ * is not necessary to check this if we use a local pubring. Hmmmm. */ int -check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel ) +check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel ) { - int trustlevel = 0; + TRUSTREC rec; + unsigned trustlevel = TRUST_UNKNOWN; + int rc=0; + + if( DBG_TRUST ) + log_info("check_trust() called.\n"); + + /* get the pubkey record */ + if( pkc->local_id ) { + if( read_record( pkc->local_id, &rec ) ) { + log_error("check_trust: 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("check_trust: scan_record_by_pkc(2) failed: %s\n", + g10_errstr(rc)); + return rc; + } + else if( rc == -1 ) { + rc = insert_trust_record( pkc ); + if( rc ) { + log_error("failed to insert pubkey into trustdb: %s\n", + g10_errstr(rc)); + goto leave; + } + log_info("pubkey not in trustdb - inserted as %lu\n", + pkc->local_id ); + } + } + /* fixme: do some additional checks on the pubkey record */ + + rc = do_check( pkc->local_id, &trustlevel ); + if( rc ) { + log_error("check_trust: do_check failed: %s\n", g10_errstr(rc)); + return rc; + } - if( opt.verbose ) - log_info("check_pkc_trust() called.\n"); + leave: + if( DBG_TRUST ) + log_info("check_trust() returns trustlevel %04x.\n", trustlevel); *r_trustlevel = trustlevel; return 0; +} + + + + +/**************** + * Enumerate all keys, which are needed to build all trust paths for + * the given key. This function dies not return the key itself or + * the ultimate key. + * + * 1) create a void pointer and initialize it to NULL + * 2) pass this void pointer by reference to this function. + * Set lid to the key you want to enumerate and pass it by reference. + * 3) call this function as long as it does not return -1 + * to indicate EOF. LID does contain the next key used to build the web + * 4) Always call this function a last time with LID set to NULL, + * so that it can free it's context. + */ +int +enum_trust_web( void **context, ulong *lid ) +{ + ENUM_TRUST_WEB_CONTEXT *c = *context; + + if( !c ) { /* make a new context */ + c = m_alloc_clear( sizeof *c ); + *context = c; + if( *lid != last_trust_web_key ) + log_bug("enum_trust_web: nyi\n"); + c->tsl = last_trust_web_tslist; + c->index = 1; + } + + if( !lid ) { /* free the context */ + m_free( c ); + *context = NULL; + return 0; + } + + while( c->tsl ) { + if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) { + *lid = c->tsl->seg[c->index].lid; + c->index++; + return 0; + } + c->index = 1; + c->tsl = c->tsl->next; + } + return -1; /* eof */ +} + + +/**************** + * Return the assigned ownertrust value for the given LID + */ +int +get_ownertrust( ulong lid, unsigned *r_otrust ) +{ + TRUSTREC rec; + + if( read_record( lid, &rec ) ) { + log_error("get_ownertrust: read record failed\n"); + return G10ERR_TRUSTDB; + } + if( r_otrust ) + *r_otrust = rec.r.pubkey.ownertrust; + return 0; +} + +int +keyid_from_trustdb( ulong lid, u32 *keyid ) +{ + TRUSTREC rec; + + if( read_record( lid, &rec ) ) { + log_error("keyid_from_trustdb: read record failed\n"); + return G10ERR_TRUSTDB; + } + if( keyid ) { + keyid[0] = rec.r.pubkey.keyid[0]; + keyid[1] = rec.r.pubkey.keyid[1]; + } + return 0; +} + + +int +query_trust_record( PKT_public_cert *pkc ) +{ + TRUSTREC rec; + int rc=0; + + if( pkc->local_id ) { + if( read_record( pkc->local_id, &rec ) ) { + log_error("query_trust_record: read record failed\n"); + return G10ERR_TRUSTDB; + } + } + else { /* no local_id: scan the trustdb */ + if( (rc=scan_record_by_pkc( pkc, &rec, 2 )) && rc != -1 ) { + log_error("query_trust_record: scan_record_by_pkc(2) failed: %s\n", + g10_errstr(rc)); + return rc; + } + else if( rc == -1 ) + return rc; + } + return 0; +} + + +/**************** + * Insert a trust record into the TrustDB + * This function failes if this record already exists. + */ +int +insert_trust_record( PKT_public_cert *pkc ) +{ + TRUSTREC rec; + u32 keyid[2]; + ulong recnum; + byte *fingerprint; + size_t fingerlen; + + + 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_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.pubkey_algo = pkc->pubkey_algo; + memcpy(rec.r.pubkey.fingerprint, fingerprint, fingerlen ); + rec.r.pubkey.ownertrust = 0; + rec.r.pubkey.no_sigs = 0; + if( write_record( recnum, &rec ) ) { + log_error("insert_trust_record: write failed\n"); + return G10ERR_TRUSTDB; + } + + pkc->local_id = recnum; + + return 0; +} + + +int +update_ownertrust( ulong lid, unsigned new_trust ) +{ + TRUSTREC rec; + + if( read_record( lid, &rec ) ) { + log_error("update_ownertrust: read failed\n"); + return G10ERR_TRUSTDB; + } + /* check keyid, fingerprint etc ? */ + if( rec.rectype != 2 ) { + log_error("update_ownertrust: invalid record type\n"); + return G10ERR_TRUSTDB; + } + + rec.r.pubkey.ownertrust = new_trust; + if( write_record( lid, &rec ) ) { + log_error("update_ownertrust: write failed\n"); + return G10ERR_TRUSTDB; + } + + return 0; +} + + + +/**************** + * Kludge to prevent duplicate build_sigrecs() due to an invalid + * certificate (no selfsignature or something like this) + */ +static int +update_no_sigs( ulong lid, int no_sigs ) +{ + TRUSTREC rec; + + if( read_record( lid, &rec ) ) { + log_error("update_no_sigs: read failed\n"); + return G10ERR_TRUSTDB; + } + /* check keyid, fingerprint etc ? */ + if( rec.rectype != 2 ) { + log_error("update_no_sigs: invalid record type\n"); + return G10ERR_TRUSTDB; + } + + rec.r.pubkey.no_sigs = !!no_sigs; + if( write_record( lid, &rec ) ) { + log_error("update_no_sigs: write failed\n"); + return G10ERR_TRUSTDB; + } + + return 0; +} + + +int +verify_private_data() +{ + int rc = 0; + char *sigfile = make_filename("~/.g10", "sig", NULL ); + + if( access( sigfile, R_OK ) ) { + if( errno != ENOENT ) { + log_error("can't access %s: %s\n", sigfile, strerror(errno) ); + rc = G10ERR_TRUSTDB; + goto leave; + } + log_info("private data signature missing; creating ...\n"); + rc = sign_private_data(); + if( rc ) { + log_error("error creating %s: %s\n", sigfile, g10_errstr(rc) ); + goto leave; + } + } + + /* FIXME: verify this signature */ + + leave: + m_free(sigfile); + return rc; +} + + +int +sign_private_data() +{ + int rc; + char *sigfile = make_filename("~/.g10", "sig", NULL ); + char *secring = make_filename("~/.g10", "secring.g10", NULL ); + STRLIST list = NULL; + + add_to_strlist( &list, db_name ); + add_to_strlist( &list, secring ); + + rc = sign_file( list, 1, NULL, 0, NULL, sigfile); + + m_free(sigfile); + m_free(secring); + free_strlist(list); + return rc; } diff -urN g10-0.1.3/g10/trustdb.h g10-0.2.0/g10/trustdb.h --- g10-0.1.3/g10/trustdb.h Thu Jan 8 21:32:40 1998 +++ g10-0.2.0/g10/trustdb.h Sat Jan 24 17:19:17 1998 @@ -21,8 +21,29 @@ #ifndef G10_TRUSTDB_H #define G10_TRUSTDB_H + + +#define TRUST_UNKNOWN 0 /* not yet calculated */ +#define TRUST_EXPIRED 1 /* calculation may be invalid */ +#define TRUST_UNDEFINED 2 /* not enough informations for calculation */ +#define TRUST_NEVER 3 /* never trusted this pubkey */ +#define TRUST_MARGINAL 4 /* marginally trusted */ +#define TRUST_FULLY 5 /* fully trusted */ +#define TRUST_ULTIMATE 6 /* ultimately trusted */ + + /*-- trustdb.c --*/ -int check_trustdb( int level ); -int check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel ); +void list_trustdb(const char *username); +void list_trust_path( int max_depth, const char *username ); +int init_trustdb( int level ); +int check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel ); +int enum_trust_web( void **context, ulong *lid ); +int get_ownertrust( ulong lid, unsigned *r_otrust ); +int keyid_from_trustdb( ulong lid, u32 *keyid ); +int query_trust_record( PKT_public_cert *pkc ); +int insert_trust_record( PKT_public_cert *pkc ); +int update_ownertrust( ulong lid, unsigned new_trust ); +int verify_private_data(void); +int sign_private_data(void); #endif /*G10_TRUSTDB_H*/ diff -urN g10-0.1.3/include/cipher.h g10-0.2.0/include/cipher.h --- g10-0.1.3/include/cipher.h Fri Jan 9 10:14:35 1998 +++ g10-0.2.0/include/cipher.h Thu Jan 15 17:46:31 1998 @@ -78,6 +78,7 @@ 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 ); diff -urN g10-0.1.3/include/errors.h g10-0.2.0/include/errors.h --- g10-0.1.3/include/errors.h Thu Jan 8 10:14:52 1998 +++ g10-0.2.0/include/errors.h Fri Jan 16 17:36:34 1998 @@ -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*/ diff -urN g10-0.1.3/include/iobuf.h g10-0.2.0/include/iobuf.h --- g10-0.1.3/include/iobuf.h Wed Dec 17 13:15:03 1997 +++ g10-0.2.0/include/iobuf.h Thu Jan 22 22:39:58 1998 @@ -54,7 +54,7 @@ IOBUF chain; /* next iobuf used for i/o if any (passed to filter) */ int no, subno; const char *desc; - void *opaque; /* can be used to old any information */ + void *opaque; /* can be used to hold any information */ /* this value is copied to all instances */ }; @@ -93,6 +93,7 @@ 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 diff -urN g10-0.1.3/include/mpi.h g10-0.2.0/include/mpi.h --- g10-0.1.3/include/mpi.h Thu Jan 8 13:00:39 1998 +++ g10-0.2.0/include/mpi.h Thu Jan 15 14:15:46 1998 @@ -41,7 +41,6 @@ #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; diff -urN g10-0.1.3/include/util.h g10-0.2.0/include/util.h --- g10-0.1.3/include/util.h Wed Jan 7 19:53:03 1998 +++ g10-0.2.0/include/util.h Thu Jan 22 13:40:05 1998 @@ -58,20 +58,38 @@ /*-- 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 ); @@ -91,6 +109,7 @@ /*-- strgutil.c --*/ void free_strlist( STRLIST sl ); #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) +void add_to_strlist( STRLIST *list, const char *string ); char *memistr( char *buf, size_t buflen, const char *sub ); char *trim_spaces( char *string ); int string_count_chr( const char *string, int c ); @@ -102,7 +121,9 @@ #ifndef HAVE_STRLWR char *strlwr(char *a); #endif - +#ifndef HAVE_STRTOUL + #define strtoul(a,b,c) ((unsigned long)strtol((a),(b),(c))) +#endif /******** some macros ************/ #ifndef STR @@ -111,5 +132,6 @@ #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*/ diff -urN g10-0.1.3/mpi/longlong.h g10-0.2.0/mpi/longlong.h --- g10-0.1.3/mpi/longlong.h Thu Dec 18 11:56:36 1997 +++ g10-0.2.0/mpi/longlong.h Thu Jan 22 13:53:24 1998 @@ -1,4 +1,5 @@ /* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with g10 Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc. @@ -1440,6 +1441,7 @@ const #endif unsigned char __clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 #define count_leading_zeros(count, x) \ do { \ UWtype __xr = (x); \ diff -urN g10-0.1.3/mpi/mpi-bit.c g10-0.2.0/mpi/mpi-bit.c --- g10-0.1.3/mpi/mpi-bit.c Fri Dec 19 10:13:01 1997 +++ g10-0.2.0/mpi/mpi-bit.c Sun Jan 25 20:16:39 1998 @@ -26,14 +26,38 @@ #include "longlong.h" +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +__clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + + + + + + + /**************** * Return the number of bits in A. */ 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]; diff -urN g10-0.1.3/mpi/mpi-internal.h g10-0.2.0/mpi/mpi-internal.h --- g10-0.1.3/mpi/mpi-internal.h Mon Dec 22 21:03:21 1997 +++ g10-0.2.0/mpi/mpi-internal.h Fri Jan 16 12:08:56 1998 @@ -193,7 +193,7 @@ 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); diff -urN g10-0.1.3/mpi/mpi-pow.c g10-0.2.0/mpi/mpi-pow.c --- g10-0.1.3/mpi/mpi-pow.c Mon Dec 22 16:47:00 1997 +++ g10-0.2.0/mpi/mpi-pow.c Fri Jan 16 12:19:50 1998 @@ -52,7 +52,7 @@ 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; diff -urN g10-0.1.3/mpi/mpicoder.c g10-0.2.0/mpi/mpicoder.c --- g10-0.1.3/mpi/mpicoder.c Tue Dec 9 09:06:43 1997 +++ g10-0.2.0/mpi/mpicoder.c Fri Jan 16 12:07:58 1998 @@ -41,36 +41,23 @@ 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 @@ 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 ); diff -urN g10-0.1.3/mpi/mpiutil.c g10-0.2.0/mpi/mpiutil.c --- g10-0.1.3/mpi/mpiutil.c Tue Dec 9 09:07:04 1997 +++ g10-0.2.0/mpi/mpiutil.c Fri Jan 16 12:13:37 1998 @@ -45,7 +45,7 @@ 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 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; diff -urN g10-0.1.3/util/Makefile.in g10-0.2.0/util/Makefile.in --- g10-0.1.3/util/Makefile.in Mon Jan 12 11:01:41 1998 +++ g10-0.2.0/util/Makefile.in Sun Jan 25 20:22:12 1998 @@ -146,8 +146,8 @@ || ln $(srcdir)/$$file $(distdir)/$$file 2> /dev/null \ || cp -p $(srcdir)/$$file $(distdir)/$$file; \ done -argparse.o: argparse.c ../include/util.h ../include/errors.h \ - ../include/types.h ../include/mpi.h ../include/iobuf.h \ +argparse.o: argparse.c ../include/util.h ../include/types.h \ + ../include/errors.h ../include/mpi.h ../include/iobuf.h \ ../include/memory.h errors.o: errors.c ../include/errors.h fileutil.o: fileutil.c ../include/util.h ../include/errors.h \ diff -urN g10-0.1.3/util/argparse.c g10-0.2.0/util/argparse.c --- g10-0.1.3/util/argparse.c Mon Dec 15 22:37:59 1997 +++ g10-0.2.0/util/argparse.c Sat Jan 24 12:38:36 1998 @@ -188,7 +188,6 @@ 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]; @@ -287,7 +286,7 @@ else if( state == 3 ) { /* skip leading spaces of the argument */ if( !isspace(c) ) { i = 0; - keyword[i] = c; + keyword[i++] = c; state = 4; } } diff -urN g10-0.1.3/util/errors.c g10-0.2.0/util/errors.c --- g10-0.1.3/util/errors.c Fri Nov 28 20:46:32 1997 +++ g10-0.2.0/util/errors.c Mon Jan 19 18:01:31 1998 @@ -33,6 +33,8 @@ #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,8 +48,9 @@ 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_USER_ID ,"No such user id") X(NO_SECKEY ,"Secret key not available") X(WRONG_SECKEY ,"Wrong secret key used") X(UNSUPPORTED ,"Not supported") @@ -61,8 +64,10 @@ 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; diff -urN g10-0.1.3/util/iobuf.c g10-0.2.0/util/iobuf.c --- g10-0.1.3/util/iobuf.c Wed Jan 7 13:11:13 1998 +++ g10-0.2.0/util/iobuf.c Fri Jan 16 12:28:43 1998 @@ -40,6 +40,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } } +/**************** + * 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 @@ iobuf_in_block_mode( IOBUF a ) { if( a && a->filter == block_filter ) - return 1; /* yes */ + return 1; /* yes */ return 0; /* no */ } diff -urN g10-0.1.3/util/logger.c g10-0.2.0/util/logger.c --- g10-0.1.3/util/logger.c Fri Jan 2 18:37:16 1998 +++ g10-0.2.0/util/logger.c Fri Jan 16 12:24:10 1998 @@ -120,15 +120,17 @@ 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 diff -urN g10-0.1.3/util/strgutil.c g10-0.2.0/util/strgutil.c --- g10-0.1.3/util/strgutil.c Wed Jan 7 20:15:04 1998 +++ g10-0.2.0/util/strgutil.c Tue Jan 13 17:04:14 1998 @@ -37,6 +37,18 @@ } } + +void +add_to_strlist( STRLIST *list, const char *string ) +{ + STRLIST sl; + + sl = m_alloc( sizeof *sl + strlen(string)); + strcpy(sl->d, string); + sl->next = *list; + *list = sl; +} + /**************** * look for the substring SUB in buffer and return a pointer to that * substring in BUF or NULL if not found. diff -urN g10-0.1.3/util/ttyio.c g10-0.2.0/util/ttyio.c --- g10-0.1.3/util/ttyio.c Mon Jan 5 20:53:32 1998 +++ g10-0.2.0/util/ttyio.c Fri Jan 16 12:34:40 1998 @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef HAVE_TCGETATTR #include #endif @@ -99,7 +100,6 @@ char *buf; byte cbuf[1]; int c, n, i; - FILE *fp; #ifdef HAVE_TCGETATTR struct termios termsave; #endif