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