diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 35 | ||||
-rw-r--r-- | g10/Makefile.am | 3 | ||||
-rw-r--r-- | g10/Makefile.in | 13 | ||||
-rw-r--r-- | g10/armor.c | 1 | ||||
-rw-r--r-- | g10/cipher.c | 4 | ||||
-rw-r--r-- | g10/dsa.c | 5 | ||||
-rw-r--r-- | g10/g10.c | 6 | ||||
-rw-r--r-- | g10/getkey.c | 656 | ||||
-rw-r--r-- | g10/keydb.h | 5 | ||||
-rw-r--r-- | g10/keyid.c | 88 | ||||
-rw-r--r-- | g10/keylist.c | 1 | ||||
-rw-r--r-- | g10/main.h | 3 | ||||
-rw-r--r-- | g10/mainproc.c | 2 | ||||
-rw-r--r-- | g10/packet.h | 1 | ||||
-rw-r--r-- | g10/parse-packet.c | 16 | ||||
-rw-r--r-- | g10/ringedit.c | 56 | ||||
-rw-r--r-- | g10/sig-check.c | 22 | ||||
-rw-r--r-- | g10/sign.c | 4 | ||||
-rw-r--r-- | g10/signal.c | 74 | ||||
-rw-r--r-- | g10/trustdb.c | 10 |
20 files changed, 633 insertions, 372 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index c64144117..66c5b7554 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,38 @@ +Thu Mar 19 15:22:36 1998 Werner Koch ([email protected]) + + * ringedit.c (keyring_enum): Fixed problem with reading too + many packets. Add support to read secret keyrings. + + * getkey.c (scan_keyring): Removed + (lookup): New to replace scan_keyring. + (scan_secret_keyring): Removed. + (lookup_skc): New. + +Wed Mar 18 11:47:34 1998 Werner Koch ([email protected]) + + * ringedit.c (enum_keyblocks): New read mode 11. + + * keyid.c (elg_fingerprint_md): New and changed all other functions + to call this if the packet version is 4 or above. + +Tue Mar 17 20:46:16 1998 Werner Koch ([email protected]) + + * parse-packet.c (parse_certificate): Add listing support for subkeys. + +Tue Mar 17 20:32:22 1998 Werner Koch ([email protected]) + + * armor.c (is_armored): Allow marker packet. + +Thu Mar 12 13:36:49 1998 Werner Koch ([email protected]) + + * trustdb.c (check_trust): Checks timestamp of pubkey. + * sig-check. (do_check): Compares timestamps. + +Tue Mar 10 17:01:56 1998 Werner Koch ([email protected]) + + * g10.c (main): Add call to init_signals. + * signal.c: New. + Mon Mar 9 12:43:42 1998 Werner Koch ([email protected]) * dsa.c: New diff --git a/g10/Makefile.am b/g10/Makefile.am index edfdba412..baf3d62e0 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -50,7 +50,8 @@ common_source = \ encode.c \ revoke.c \ keylist.c \ - sig-check.c + sig-check.c \ + signal.c gpg_SOURCES = g10.c \ $(common_source) \ diff --git a/g10/Makefile.in b/g10/Makefile.in index cc4b69b36..a88b10eed 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -142,7 +142,8 @@ common_source = \ encode.c \ revoke.c \ keylist.c \ - sig-check.c + sig-check.c \ + signal.c gpg_SOURCES = g10.c \ $(common_source) \ @@ -170,7 +171,8 @@ pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \ textfilter.o cipher.o elg.o dsa.o rsa.o openfile.o keyid.o trustdb.o \ parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \ import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \ -encode.o revoke.o keylist.o sig-check.o verify.o decrypt.o keygen.o +encode.o revoke.o keylist.o sig-check.o signal.o verify.o decrypt.o \ +keygen.o gpg_LDADD = $(LDADD) gpg_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a @@ -180,7 +182,8 @@ free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o \ mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o dsa.o rsa.o \ openfile.o keyid.o trustdb.o parse-packet.o passphrase.o pubkey-enc.o \ seckey-cert.o seskey.o import.o export.o comment.o status.o sign.o \ -plaintext.o encr-data.o encode.o revoke.o keylist.o sig-check.o +plaintext.o encr-data.o encode.o revoke.o keylist.o sig-check.o \ +signal.o gpgm_LDADD = $(LDADD) gpgm_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \ ../util/libutil.a @@ -204,8 +207,8 @@ DEP_FILES = .deps/armor.P .deps/build-packet.P .deps/cipher.P \ .deps/openfile.P .deps/parse-packet.P .deps/passphrase.P \ .deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P .deps/revoke.P \ .deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P .deps/seskey.P \ -.deps/sig-check.P .deps/sign.P .deps/skclist.P .deps/status.P \ -.deps/textfilter.P .deps/trustdb.P .deps/verify.P +.deps/sig-check.P .deps/sign.P .deps/signal.P .deps/skclist.P \ +.deps/status.P .deps/textfilter.P .deps/trustdb.P .deps/verify.P SOURCES = $(gpg_SOURCES) $(gpgm_SOURCES) OBJECTS = $(gpg_OBJECTS) $(gpgm_OBJECTS) diff --git a/g10/armor.c b/g10/armor.c index 3192e95b3..848019018 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -150,6 +150,7 @@ is_armored( byte *buf ) return 1; /* invalid packet: assume it is armored */ pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf); switch( pkttype ) { + case PKT_MARKER: case PKT_PUBLIC_CERT: case PKT_SECRET_CERT: case PKT_PUBKEY_ENC: diff --git a/g10/cipher.c b/g10/cipher.c index 43f0afb21..47b9aaffe 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -47,10 +47,10 @@ cipher_filter( void *opaque, int control, cipher_filter_context_t *cfx = opaque; int rc=0; - if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypted */ + if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */ rc = -1; /* FIXME:*/ } - else if( control == IOBUFCTRL_FLUSH ) { /* encrypted */ + else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ assert(a); if( !cfx->header ) { PACKET pkt; @@ -54,7 +54,10 @@ g10_dsa_sign( PKT_secret_cert *skc, PKT_signature *sig, sig->digest_start[1] = dp[1]; sig->d.dsa.r = mpi_alloc( mpi_get_nlimbs(skc->d.dsa.p) ); sig->d.dsa.s = mpi_alloc( mpi_get_nlimbs(skc->d.dsa.p) ); - frame = encode_md_value( md, mpi_get_nbits(skc->d.dsa.p)); + frame = mpi_alloc( (md_digest_length(digest_algo)+BYTES_PER_MPI_LIMB-1) + / BYTES_PER_MPI_LIMB ); + mpi_set_buffer( frame, md_read(md, digest_algo), + md_digest_length(digest_algo), 0 ); skey.p = skc->d.elg.p; skey.g = skc->d.elg.g; skey.y = skc->d.elg.y; @@ -31,6 +31,7 @@ #include <string.h> #include <unistd.h> + #include "packet.h" #include "iobuf.h" #include "memory.h" @@ -99,7 +100,7 @@ static ARGPARSE_OPTS opts[] = { #endif { 'o', "output", 2, N_("use as output file")}, { 'v', "verbose", 0, N_("verbose") }, - { 'n', "dry-run", 0, N_("don't make any changes") }, + { 'n', "dry-run", 0, N_("do not make any changes") }, { 500, "batch", 0, N_("batch mode: never ask")}, { 501, "yes", 0, N_("assume yes on most questions")}, { 502, "no", 0, N_("assume no on most questions")}, @@ -275,7 +276,7 @@ build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) ) static void i18n_init(void) { - #ifdef HAVE_LIBINTL + #ifdef ENABLE_NLS #ifdef HAVE_LC_MESSAGES setlocale( LC_MESSAGES, "" ); #else @@ -393,6 +394,7 @@ main( int argc, char **argv ) */ log_set_name("gpg"); secure_random_alloc(); /* put random number into secure memory */ + init_signals(); #endif i18n_init(); opt.compress = -1; /* defaults to standard compress level */ diff --git a/g10/getkey.c b/g10/getkey.c index 300e33b86..e8d9d15a5 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -68,10 +68,10 @@ static pkc_cache_entry_t pkc_cache; static int pkc_cache_entries; /* number of entries in pkc cache */ -static int scan_keyring( PKT_public_cert *pkc, u32 *keyid, - const char *name, const char *filename ); -static int scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid, - const char *name, const char *filename); +static int lookup( PKT_public_cert *pkc, + int mode, u32 *keyid, const char *name ); +static int lookup_skc( PKT_secret_cert *skc, + int mode, u32 *keyid, const char *name ); /* note this function may be called before secure memory is * available */ @@ -161,7 +161,7 @@ add_secret_keyring( const char *name ) } -void +static void cache_public_cert( PKT_public_cert *pkc ) { pkc_cache_entry_t ce; @@ -214,7 +214,7 @@ cache_user_id( PKT_user_id *uid, u32 *keyid ) for(r=user_id_db; r; r = r->next ) if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) { if( DBG_CACHE ) - log_debug("cache_user_id: already in cache\n"); + log_debug("cache_user_id: already in cache\n"); return; } @@ -241,7 +241,6 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid ) int internal = 0; int rc = 0; pkc_cache_entry_t ce; - STRLIST sl; /* lets see wether we checked the keyid already */ @@ -249,14 +248,13 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid ) if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] ) return G10ERR_NO_PUBKEY; /* already checked and not found */ - /* 1. Try to get it from our cache */ + /* Try to get it from our cache */ for( ce = pkc_cache; ce; ce = ce->next ) if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) { if( pkc ) copy_public_cert( pkc, ce->pkc ); return 0; } - /* more init stuff */ if( !pkc ) { pkc = m_alloc_clear( sizeof *pkc ); @@ -264,14 +262,12 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid ) } - /* 2. Try to get it from the keyrings */ - for(sl = keyrings; sl; sl = sl->next ) - if( !scan_keyring( pkc, keyid, NULL, sl->d ) ) - goto leave; - - /* 3. Try to get it from a key server */ + /* do a lookup */ + rc = lookup( pkc, 11, keyid, NULL ); + if( !rc ) + goto leave; - /* 4. not found: store it for future reference */ + /* not found: store it for future reference */ kl = m_alloc( sizeof *kl ); kl->keyid[0] = keyid[0]; kl->keyid[1] = keyid[1]; @@ -288,6 +284,32 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid ) } +static int +hextobyte( const byte *s ) +{ + int c; + + if( *s >= '0' && *s <= '9' ) + c = 16 * (*s - '0'); + else if( *s >= 'A' && *s <= 'F' ) + c = 16 * (10 + *s - 'A'); + else if( *s >= 'a' && *s <= 'f' ) + c = 16 * (10 + *s - 'a'); + else + return -1; + s++; + if( *s >= '0' && *s <= '9' ) + c += *s - '0'; + else if( *s >= 'A' && *s <= 'F' ) + c += 10 + *s - 'A'; + else if( *s >= 'a' && *s <= 'f' ) + c += 10 + *s - 'a'; + else + return -1; + return c; +} + + /**************** * Try to get the pubkey by the userid. This functions looks for the * first pubkey certificate which has the given name in a user_id. @@ -302,26 +324,30 @@ get_pubkey( PKT_public_cert *pkc, u32 *keyid ) * (Not yet implemented) * - If the username starts with a left angle, we assume it is a complete * email address and look only at this part. + * - If the username starts with a '.', we assume it is the ending + * part of an email address + * - If the username starts with an '@', we assume it is a part of an + * email address * - If the userid start with an '=' an exact compare is done; this may * also follow the keyid in which case both parts are matched. - * (Not yet implemented) - * + * - If the userid starts with a '*' a case insensitive substring search is + * done (This is also the default). */ int get_pubkey_byname( PKT_public_cert *pkc, const char *name ) { int internal = 0; int rc = 0; - STRLIST sl; const char *s; u32 keyid[2] = {0}; /* init to avoid compiler warning */ - int use_keyid=0; + byte fprint[20]; + int mode = 0; /* check what kind of name it is */ for(s = name; *s && isspace(*s); s++ ) ; - if( isdigit( *s ) ) { /* a keyid */ - int i; + if( isdigit( *s ) ) { /* a keyid or a fingerprint */ + int i, j; char buf[9]; if( *s == '0' && s[1] == 'x' && isxdigit(s[2]) ) @@ -334,7 +360,7 @@ get_pubkey_byname( PKT_public_cert *pkc, const char *name ) if( i==9 ) s++; keyid[1] = strtoul( s, NULL, 16 ); - use_keyid++; + mode = 10; } else if( i == 16 || (i == 17 && *s == '0') ) { /* complete keyid */ if( i==17 ) @@ -342,51 +368,73 @@ get_pubkey_byname( PKT_public_cert *pkc, const char *name ) mem2str(buf, s, 9 ); keyid[0] = strtoul( buf, NULL, 16 ); keyid[1] = strtoul( s+8, NULL, 16 ); - return get_pubkey( pkc, keyid ); + mode = 11; + } + else if( i == 32 || ( i == 33 && *s == '0' ) ) { /* md5 fingerprint */ + if( i==33 ) + s++; + memset(fprint+16, 4, 0); + for(j=0; !rc && j < 16; j++, s+=2 ) { + int c = hextobyte( s ); + if( c == -1 ) + rc = G10ERR_INV_USER_ID; + else + fprint[j] = c; + } + mode = 16; + } + else if( i == 40 || ( i == 41 && *s == '0' ) ) { /* sha1/rmd160 fprint*/ + if( i==33 ) + s++; + for(j=0; !rc && j < 20; j++, s+=2 ) { + int c = hextobyte( s ); + if( c == -1 ) + rc = G10ERR_INV_USER_ID; + else + fprint[j] = c; + } + mode = 20; } else rc = G10ERR_INV_USER_ID; } + else if( *s == '=' ) { /* exact search */ + mode = 1; + s++; + } + else if( *s == '*' ) { /* substring search */ + mode = 2; + s++; + } else if( *s == '<' ) { /* an email address */ - /* for now handled like a substring */ - /* a keyserver might use this for quicker access */ + mode = 3; } - else if( *s == '=' ) { /* exact search */ - rc = G10ERR_INV_USER_ID; /* nox yet implemented */ + else if( *s == '@' ) { /* a part of an email address */ + mode = 4; + s++; } - else if( *s == '#' ) { /* use local id */ - rc = G10ERR_INV_USER_ID; /* nox yet implemented */ + else if( *s == '.' ) { /* an email address, compare from end */ + mode = 5; + s++; } - else if( *s == '*' ) { /* substring search */ - name++; + else if( *s == '#' ) { /* use local id */ + rc = G10ERR_INV_USER_ID; /* not yet implemented */ } else if( !*s ) /* empty string */ rc = G10ERR_INV_USER_ID; + else + mode = 2; if( rc ) goto leave; - - if( !pkc ) { pkc = m_alloc_clear( sizeof *pkc ); internal++; } - /* 2. Try to get it from the keyrings */ - for(sl = keyrings; sl; sl = sl->next ) - if( use_keyid ) { - if( !scan_keyring( pkc, keyid, name, sl->d ) ) - goto leave; - } - else { - if( !scan_keyring( pkc, NULL, name, sl->d ) ) - goto leave; - } - /* 3. Try to get it from a key server */ - - /* 4. not found: store it for future reference */ - rc = G10ERR_NO_PUBKEY; + rc = mode < 16? lookup( pkc, mode, keyid, name ) + : lookup( pkc, mode, keyid, fprint ); leave: if( internal ) @@ -401,23 +449,16 @@ get_pubkey_byname( PKT_public_cert *pkc, const char *name ) int get_seckey( PKT_secret_cert *skc, u32 *keyid ) { - STRLIST sl; - int rc=0; - - for(sl = secret_keyrings; sl; sl = sl->next ) - if( !(rc=scan_secret_keyring( skc, keyid, NULL, sl->d )) ) - goto found; - /* fixme: look at other places */ - goto leave; + int rc; - found: - /* get the secret key (this may prompt for a passprase to - * unlock the secret key - */ - if( (rc = check_secret_key( skc )) ) - goto leave; + rc = lookup_skc( skc, 11, keyid, NULL ); + if( !rc ) { + /* check the secret key (this may prompt for a passprase to + * unlock the secret key + */ + rc = check_secret_key( skc ); + } - leave: return rc; } @@ -430,18 +471,10 @@ int seckey_available( u32 *keyid ) { PKT_secret_cert *skc; - STRLIST sl; - int rc=0; + int rc; skc = m_alloc_clear( sizeof *skc ); - for(sl = secret_keyrings; sl; sl = sl->next ) - if( !(rc=scan_secret_keyring( skc, keyid, NULL, sl->d )) ) - goto found; - /* fixme: look at other places */ - goto leave; - - found: - leave: + rc = lookup_skc( skc, 11, keyid, NULL ); free_secret_cert( skc ); return rc; } @@ -455,288 +488,295 @@ seckey_available( u32 *keyid ) int get_seckey_byname( PKT_secret_cert *skc, const char *name, int unprotect ) { - STRLIST sl; - int rc=0; + int rc; - for(sl = secret_keyrings; sl; sl = sl->next ) - if( !(rc=scan_secret_keyring( skc, NULL, name, sl->d ) ) ) - goto found; - /* fixme: look at other places */ - goto leave; + /* fixme: add support for compare_name */ + rc = lookup_skc( skc, name? 2:15, NULL, name ); + if( !rc && unprotect ) + rc = check_secret_key( skc ); - found: - /* get the secret key (this may prompt for a passprase to - * unlock the secret key - */ - if( unprotect ) - if( (rc = check_secret_key( skc )) ) - goto leave; - - leave: return rc; } +static int +compare_name( const char *uid, size_t uidlen, const char *name, int mode ) +{ + int i; + + if( mode == 1 ) { /* exact match */ + for(i=0; name[i] && uidlen; i++, uidlen-- ) + if( uid[i] != name[i] ) + break; + if( !uidlen && !name[i] ) + return 0; /* found */ + } + else if( mode == 2 ) { /* case insensitive substring */ + if( memistr( uid, uidlen, name ) ) + return 0; + } + else if( mode == 3 ) { /* case insensitive email address */ + /* FIXME: not yet implemented */ + if( memistr( uid, uidlen, name ) ) + return 0; + } + else if( mode == 4 ) { /* email substring */ + /* FIXME: not yet implemented */ + if( memistr( uid, uidlen, name ) ) + return 0; + } + else if( mode == 5 ) { /* email from end */ + /* FIXME: not yet implemented */ + if( memistr( uid, uidlen, name ) ) + return 0; + } + else + BUG(); + return -1; /* not found */ +} /**************** - * scan the keyring and look for either the keyid or the name. - * If both, keyid and name are given, look for keyid but use only - * the low word of it (name is only used as a flag to indicate this mode - * of operation). + * Lookup a key by scanning all keyrings + * mode 1 = lookup by NAME (exact) + * 2 = lookup by NAME (substring) + * 3 = lookup by NAME (email address) + * 4 = email address (substring) + * 5 = email address (compare from end) + * 10 = lookup by short KEYID (don't care about keyid[0]) + * 11 = lookup by long KEYID + * 15 = Get the first key. + * 16 = lookup by 16 byte fingerprint which is stored in NAME + * 20 = lookup by 20 byte fingerprint which is stored in NAME + * Caller must provide an empty PKC, if the pubkey_algo is filled in, only + * a key of this algo will be returned. */ static int -scan_keyring( PKT_public_cert *pkc, u32 *keyid, - const char *name, const char *filename ) +lookup( PKT_public_cert *pkc, int mode, u32 *keyid, const char *name ) { - compress_filter_context_t cfx; - int rc=0; - int found = 0; - IOBUF a; - PACKET pkt; - int save_mode; - u32 akeyid[2]; - PKT_public_cert *last_pk = NULL; - int shortkeyid; - - shortkeyid = keyid && name; - if( shortkeyid ) - name = NULL; /* not used anymore */ - - if( !(a = iobuf_open( filename ) ) ) { - log_debug("scan_keyring: can't open '%s'\n", filename ); - return G10ERR_KEYRING_OPEN; + int rc; + KBNODE keyblock = NULL; + KBPOS kbpos; + + rc = enum_keyblocks( 0, &kbpos, &keyblock ); + if( rc ) { + if( rc == -1 ) + rc = G10ERR_NO_PUBKEY; + else if( rc ) + log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) ); + goto leave; } - if( !DBG_CACHE ) - ; - else if( shortkeyid ) - log_debug("scan_keyring %s for %08lx\n", filename, (ulong)keyid[1] ); - else if( name ) - log_debug("scan_keyring %s for '%s'\n", filename, name ); - else if( keyid ) - log_debug("scan_keyring %s for %08lx %08lx\n", filename, - (ulong)keyid[0], (ulong)keyid[1] ); - else - log_debug("scan_keyring %s (all)\n", filename ); - - save_mode = set_packet_list_mode(0); - init_packet(&pkt); - while( (rc=parse_packet(a, &pkt)) != -1 ) { - if( rc ) - ; /* e.g. unknown packet */ - else if( keyid && found && pkt.pkttype == PKT_PUBLIC_CERT ) { - log_error("Hmmm, pubkey without an user id in '%s'\n", filename); - goto leave; - } - else if( pkt.pkttype == PKT_COMPRESSED ) { - memset( &cfx, 0, sizeof cfx ); - if( pkt.pkt.compressed->algorithm == 1 ) - cfx.pgpmode = 1; - else if( pkt.pkt.compressed->algorithm != 2 ){ - rc = G10ERR_COMPR_ALGO; - log_error("compressed keyring: %s\n", g10_errstr(rc) ); - break; - } - - pkt.pkt.compressed->buf = NULL; - iobuf_push_filter( a, compress_filter, &cfx ); - } - else if( keyid && pkt.pkttype == PKT_PUBLIC_CERT ) { - switch( pkt.pkt.public_cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_DSA: - case PUBKEY_ALGO_RSA: - keyid_from_pkc( pkt.pkt.public_cert, akeyid ); - if( (shortkeyid || akeyid[0] == keyid[0]) - && akeyid[1] == keyid[1] ) { - copy_public_cert( pkc, pkt.pkt.public_cert ); - found++; + while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { + KBNODE k, kk; + if( mode < 10 ) { /* name lookup */ + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_USER_ID + && !compare_name( k->pkt->pkt.user_id->name, + k->pkt->pkt.user_id->len, name, mode)) { + /* we found a matching name, look for the key */ + for(kk=keyblock; kk; kk = kk->next ) + if( ( kk->pkt->pkttype == PKT_PUBLIC_CERT + || kk->pkt->pkttype == PKT_PUBKEY_SUBCERT ) + && ( !pkc->pubkey_algo + || pkc->pubkey_algo + == kk->pkt->pkt.public_cert->pubkey_algo)) + break; + if( kk ) { + u32 aki[2]; + keyid_from_pkc( kk->pkt->pkt.public_cert, aki ); + cache_user_id( k->pkt->pkt.user_id, aki ); + k = kk; + break; + } + else + log_error("No key for userid\n"); } - break; - default: - log_error("cannot handle pubkey algo %d\n", - pkt.pkt.public_cert->pubkey_algo); } } - else if( keyid && found && pkt.pkttype == PKT_USER_ID ) { - cache_user_id( pkt.pkt.user_id, keyid ); - goto leave; - } - else if( name && pkt.pkttype == PKT_PUBLIC_CERT ) { - if( last_pk ) - free_public_cert(last_pk); - last_pk = pkt.pkt.public_cert; - pkt.pkt.public_cert = NULL; - } - else if( name && pkt.pkttype == PKT_USER_ID ) { - if( memistr( pkt.pkt.user_id->name, pkt.pkt.user_id->len, name )) { - if( !last_pk ) - log_error("Ooops: no pubkey for userid '%.*s'\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name); - else if( pkc->pubkey_algo && - pkc->pubkey_algo != last_pk->pubkey_algo ) - log_info("skipping id '%.*s': want algo %d, found %d\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name, - pkc->pubkey_algo, last_pk->pubkey_algo ); - else { - copy_public_cert( pkc, last_pk ); - goto leave; - } + else { /* keyid or fingerprint lookup */ + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_PUBLIC_CERT + || k->pkt->pkttype == PKT_PUBKEY_SUBCERT ) { + if( mode == 10 || mode == 11 ) { + u32 aki[2]; + keyid_from_pkc( k->pkt->pkt.public_cert, aki ); + if( aki[1] == keyid[1] + && ( mode == 10 || aki[0] == keyid[0] ) + && ( !pkc->pubkey_algo + || pkc->pubkey_algo + == k->pkt->pkt.public_cert->pubkey_algo) ){ + /* cache the userid */ + for(kk=keyblock; kk; kk = kk->next ) + if( kk->pkt->pkttype == PKT_USER_ID ) + break; + if( kk ) + cache_user_id( kk->pkt->pkt.user_id, aki ); + else + log_error("No userid for key\n"); + break; /* found */ + } + } + else if( mode == 15 ) { /* get the first key */ + if( !pkc->pubkey_algo + || pkc->pubkey_algo + == k->pkt->pkt.public_cert->pubkey_algo ) + break; + } + else if( mode == 16 || mode == 20 ) { + size_t an; + byte *afp = fingerprint_from_pkc( + k->pkt->pkt.public_cert, &an ); + if( an == mode && !memcmp( afp, name, an) + && ( !pkc->pubkey_algo + || pkc->pubkey_algo + == k->pkt->pkt.public_cert->pubkey_algo) ) { + m_free(afp); + break; + } + m_free(afp); + } + else + BUG(); + } /* end compare public keys */ } } - else if( !keyid && !name && pkt.pkttype == PKT_PUBLIC_CERT ) { - if( last_pk ) - free_public_cert(last_pk); - last_pk = pkt.pkt.public_cert; - pkt.pkt.public_cert = NULL; + if( k ) { /* found */ + assert( k->pkt->pkttype == PKT_PUBLIC_CERT + || k->pkt->pkttype == PKT_PUBKEY_SUBCERT ); + copy_public_cert( pkc, k->pkt->pkt.public_cert ); + break; /* enumeration */ } - else if( !keyid && !name && pkt.pkttype == PKT_USER_ID ) { - if( !last_pk ) - log_error("Ooops: no pubkey for userid '%.*s'\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name); - else { - if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL - || last_pk->pubkey_algo == PUBKEY_ALGO_DSA - || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) { - keyid_from_pkc( last_pk, akeyid ); - cache_user_id( pkt.pkt.user_id, akeyid ); - } - cache_public_cert( last_pk ); - } - } - free_packet(&pkt); + release_kbnode( keyblock ); + keyblock = NULL; } - rc = G10ERR_NO_PUBKEY; + if( rc == -1 ) + rc = G10ERR_NO_PUBKEY; + else if( rc ) + log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc)); leave: - if( last_pk ) - free_public_cert(last_pk); - free_packet(&pkt); - iobuf_close(a); - set_packet_list_mode(save_mode); + enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ + release_kbnode( keyblock ); return rc; } - /**************** - * This is the function to get a secret key. We use an extra function, - * so that we can easily add special handling for secret keyrings - * PKT returns the secret key certificate. + * Ditto for secret keys */ static int -scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid, - const char *name, const char *filename ) +lookup_skc( PKT_secret_cert *skc, int mode, u32 *keyid, const char *name ) { - int rc=0; - int found = 0; - IOBUF a; - PACKET pkt; - int save_mode; - u32 akeyid[2]; - PKT_secret_cert *last_pk = NULL; - int get_first; - u32 dummy_keyid[2]; - - get_first = !keyid && !name; - if( get_first ) - keyid = dummy_keyid; - - if( !(a = iobuf_open( filename ) ) ) { - log_debug("scan_secret_keyring: can't open '%s'\n", filename ); - return G10ERR_KEYRING_OPEN; + int rc; + KBNODE keyblock = NULL; + KBPOS kbpos; + + rc = enum_keyblocks( 5 /* open secret */, &kbpos, &keyblock ); + if( rc ) { + if( rc == -1 ) + rc = G10ERR_NO_PUBKEY; + else if( rc ) + log_error("enum_keyblocks(open secret) failed: %s\n", g10_errstr(rc) ); + goto leave; } - save_mode = set_packet_list_mode(0); - init_packet(&pkt); - while( (rc=parse_packet(a, &pkt)) != -1 ) { - if( rc ) - ; /* e.g. unknown packet */ - else if( keyid && found && pkt.pkttype == PKT_SECRET_CERT ) { - log_error("Hmmm, seckey without an user id in '%s'\n", filename); - goto leave; - } - else if( keyid && pkt.pkttype == PKT_SECRET_CERT ) { - switch( pkt.pkt.secret_cert->pubkey_algo ) { - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_DSA: - case PUBKEY_ALGO_RSA: - if( get_first ) { - copy_secret_cert( skc, pkt.pkt.secret_cert ); - found++; - } - else { - keyid_from_skc( pkt.pkt.secret_cert, akeyid ); - if( (akeyid[0] == keyid[0] && akeyid[1] == keyid[1]) ) { - copy_secret_cert( skc, pkt.pkt.secret_cert ); - found++; + while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { + KBNODE k, kk; + if( mode < 10 ) { /* name lookup */ + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_USER_ID + && !compare_name( k->pkt->pkt.user_id->name, + k->pkt->pkt.user_id->len, name, mode)) { + /* we found a matching name, look for the key */ + for(kk=keyblock; kk; kk = kk->next ) + if( ( kk->pkt->pkttype == PKT_SECRET_CERT + || kk->pkt->pkttype == PKT_SECKEY_SUBCERT ) + && ( !skc->pubkey_algo + || skc->pubkey_algo + == kk->pkt->pkt.secret_cert->pubkey_algo)) + break; + if( kk ) { + u32 aki[2]; + keyid_from_skc( kk->pkt->pkt.secret_cert, aki ); + cache_user_id( k->pkt->pkt.user_id, aki ); + k = kk; + break; } + else + log_error("No key for userid (in skc)\n"); } - break; - default: - log_error("cannot handle pubkey algo %d\n", - pkt.pkt.secret_cert->pubkey_algo); } } - else if( keyid && found && pkt.pkttype == PKT_USER_ID ) { - goto leave; - } - else if( name && pkt.pkttype == PKT_SECRET_CERT ) { - if( last_pk ) - free_secret_cert(last_pk); - last_pk = pkt.pkt.secret_cert; - pkt.pkt.secret_cert = NULL; - } - else if( name && pkt.pkttype == PKT_USER_ID ) { - if( memistr( pkt.pkt.user_id->name, pkt.pkt.user_id->len, name )) { - if( !last_pk ) - log_error("Ooops: no seckey for userid '%.*s'\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name); - else if( skc->pubkey_algo && - skc->pubkey_algo != last_pk->pubkey_algo ) - log_info("skipping id '%.*s': want algo %d, found %d\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name, - skc->pubkey_algo, last_pk->pubkey_algo ); - else { - copy_secret_cert( skc, last_pk ); - goto leave; - } + else { /* keyid or fingerprint lookup */ + for(k=keyblock; k; k = k->next ) { + if( k->pkt->pkttype == PKT_SECRET_CERT + || k->pkt->pkttype == PKT_SECKEY_SUBCERT ) { + if( mode == 10 || mode == 11 ) { + u32 aki[2]; + keyid_from_skc( k->pkt->pkt.secret_cert, aki ); + if( aki[1] == keyid[1] + && ( mode == 10 || aki[0] == keyid[0] ) + && ( !skc->pubkey_algo + || skc->pubkey_algo + == k->pkt->pkt.secret_cert->pubkey_algo) ){ + /* cache the userid */ + for(kk=keyblock; kk; kk = kk->next ) + if( kk->pkt->pkttype == PKT_USER_ID ) + break; + if( kk ) + cache_user_id( kk->pkt->pkt.user_id, aki ); + else + log_error("No userid for key\n"); + break; /* found */ + } + } + else if( mode == 15 ) { /* get the first key */ + if( !skc->pubkey_algo + || skc->pubkey_algo + == k->pkt->pkt.secret_cert->pubkey_algo ) + break; + } + else if( mode == 16 || mode == 20 ) { + size_t an; + byte *afp = fingerprint_from_skc( + k->pkt->pkt.secret_cert, &an ); + if( an == mode && !memcmp( afp, name, an) + && ( !skc->pubkey_algo + || skc->pubkey_algo + == k->pkt->pkt.secret_cert->pubkey_algo) ) { + m_free(afp); + break; + } + m_free(afp); + } + else + BUG(); + } /* end compare secret keys */ } } - else if( !keyid && !name && pkt.pkttype == PKT_SECRET_CERT ) { - if( last_pk ) - free_secret_cert(last_pk); - last_pk = pkt.pkt.secret_cert; - pkt.pkt.secret_cert = NULL; + if( k ) { /* found */ + assert( k->pkt->pkttype == PKT_SECRET_CERT + || k->pkt->pkttype == PKT_SECKEY_SUBCERT ); + copy_secret_cert( skc, k->pkt->pkt.secret_cert ); + break; /* enumeration */ } - else if( !keyid && !name && pkt.pkttype == PKT_USER_ID ) { - if( !last_pk ) - log_error("Ooops: no seckey for userid '%.*s'\n", - pkt.pkt.user_id->len, pkt.pkt.user_id->name); - else { - if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL - || last_pk->pubkey_algo == PUBKEY_ALGO_DSA - || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) { - keyid_from_skc( last_pk, akeyid ); - cache_user_id( pkt.pkt.user_id, akeyid ); - } - } - } - free_packet(&pkt); + release_kbnode( keyblock ); + keyblock = NULL; } - rc = G10ERR_NO_SECKEY; + if( rc == -1 ) + rc = G10ERR_NO_PUBKEY; + else if( rc ) + log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc)); leave: - if( last_pk ) - free_secret_cert(last_pk); - free_packet(&pkt); - iobuf_close(a); - set_packet_list_mode(save_mode); + enum_keyblocks( 2, &kbpos, &keyblock ); /* close */ + release_kbnode( keyblock ); return rc; } + /**************** * Enumerate all secret keys. Caller must use these procedure: * 1) create a void pointer and initialize it to NULL diff --git a/g10/keydb.h b/g10/keydb.h index a115578da..6a2425272 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -52,6 +52,7 @@ struct keyblock_pos_struct { ulong offset; /* position information */ unsigned count; /* length of the keyblock in packets */ IOBUF fp; /* used by enum_keyblocks */ + int secret; /* working on a secret keyring */ PACKET *pkt; /* ditto */ }; typedef struct keyblock_pos_struct KBPOS; @@ -102,8 +103,8 @@ int make_dek_from_passphrase( DEK *dek, int mode, byte *salt ); void add_keyring( const char *name ); const char *get_keyring( int sequence ); void add_secret_keyring( const char *name ); -void cache_public_cert( PKT_public_cert *pkc ); -void cache_user_id( PKT_user_id *uid, u32 *keyid ); +/*void cache_public_cert( PKT_public_cert *pkc ); +void cache_user_id( PKT_user_id *uid, u32 *keyid );*/ int get_pubkey( PKT_public_cert *pkc, u32 *keyid ); int get_pubkey_byname( PKT_public_cert *pkc, const char *name ); int get_seckey( PKT_secret_cert *skc, u32 *keyid ); diff --git a/g10/keyid.c b/g10/keyid.c index ef7b1ba1b..da426aa2a 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -106,6 +106,56 @@ v3_elg_fingerprint_md( PKT_public_cert *pkc ) } static MD_HANDLE +elg_fingerprint_md( PKT_public_cert *pkc ) +{ + MD_HANDLE md; + byte *buf1, *buf3, *buf4 ; + byte *p1, *p3, *p4; + unsigned n1, n3, n4; + unsigned nb1, nb3, nb4; + unsigned n; + + nb1 = mpi_get_nbits(pkc->d.dsa.p); + p1 = buf1 = mpi_get_buffer( pkc->d.dsa.p, &n1, NULL ); + for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ + ; + nb3 = mpi_get_nbits(pkc->d.dsa.g); + p3 = buf3 = mpi_get_buffer( pkc->d.dsa.g, &n3, NULL ); + for( ; !*p3 && n3; p3++, n3-- ) + ; + nb4 = mpi_get_nbits(pkc->d.dsa.y); + p4 = buf4 = mpi_get_buffer( pkc->d.dsa.y, &n4, NULL ); + for( ; !*p4 && n4; p4++, n4-- ) + ; + + /* calculate length of packet */ + n = 12 + n1 + n3 +n4 ; + md = md_open( DIGEST_ALGO_SHA1, 0); + + md_putc( md, 0x99 ); /* ctb */ + md_putc( md, n >> 8 ); /* 2 byte length header */ + md_putc( md, n ); + md_putc( md, 4 ); /* version */ + { u32 a = pkc->timestamp; + md_putc( md, a >> 24 ); + md_putc( md, a >> 16 ); + md_putc( md, a >> 8 ); + md_putc( md, a ); + } + md_putc( md, pkc->pubkey_algo ); + md_putc( md, nb1>>8); md_putc( md, nb1 ); md_write( md, p1, n1 ); + md_putc( md, nb3>>8); md_putc( md, nb3 ); md_write( md, p3, n3 ); + md_putc( md, nb4>>8); md_putc( md, nb4 ); md_write( md, p4, n4 ); + m_free(buf1); + m_free(buf3); + m_free(buf4); + md_final( md ); + + return md; +} + + +static MD_HANDLE dsa_fingerprint_md( PKT_public_cert *pkc ) { MD_HANDLE md; @@ -161,18 +211,22 @@ dsa_fingerprint_md( PKT_public_cert *pkc ) } static MD_HANDLE -v3_elg_fingerprint_md_skc( PKT_secret_cert *skc ) +elg_fingerprint_md_skc( PKT_secret_cert *skc ) { PKT_public_cert pkc; pkc.pubkey_algo = skc->pubkey_algo; + pkc.version = skc->version; pkc.timestamp = skc->timestamp; pkc.valid_days = skc->valid_days; pkc.pubkey_algo = skc->pubkey_algo; pkc.d.elg.p = skc->d.elg.p; pkc.d.elg.g = skc->d.elg.g; pkc.d.elg.y = skc->d.elg.y; - return v3_elg_fingerprint_md( &pkc ); + if( pkc.version < 4 ) + return v3_elg_fingerprint_md( &pkc ); + else + return elg_fingerprint_md( &pkc ); } static MD_HANDLE @@ -207,8 +261,11 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ) if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { const byte *dp; MD_HANDLE md; - md = v3_elg_fingerprint_md_skc(skc); - dp = md_read( md, DIGEST_ALGO_RMD160 ); + md = elg_fingerprint_md_skc(skc); + if( skc->version < 4 ) + dp = md_read( md, DIGEST_ALGO_RMD160 ); + else + dp = md_read( md, DIGEST_ALGO_SHA1 ); keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; lowbits = keyid[1]; @@ -250,14 +307,20 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ) if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { const byte *dp; MD_HANDLE md; - md = v3_elg_fingerprint_md(pkc); - dp = md_read( md, DIGEST_ALGO_RMD160 ); + if( pkc->version < 4 ) { + md = v3_elg_fingerprint_md(pkc); + dp = md_read( md, DIGEST_ALGO_RMD160 ); + } + else { + md = elg_fingerprint_md(pkc); + dp = md_read( md, DIGEST_ALGO_SHA1 ); + } keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; lowbits = keyid[1]; md_close(md); } - else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) { + else if( pkc->pubkey_algo == PUBKEY_ALGO_DSA ) { const byte *dp; MD_HANDLE md; md = dsa_fingerprint_md(pkc); @@ -380,6 +443,7 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len ) byte *p; pkc.pubkey_algo = skc->pubkey_algo; + pkc.version = skc->version; if( pkc.pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { pkc.timestamp = skc->timestamp; pkc.valid_days = skc->valid_days; @@ -419,8 +483,14 @@ fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { MD_HANDLE md; - md = v3_elg_fingerprint_md(pkc); - dp = md_read( md, DIGEST_ALGO_RMD160 ); + if( pkc->version < 4 ) { + md = v3_elg_fingerprint_md(pkc); + dp = md_read( md, DIGEST_ALGO_RMD160 ); + } + else { + md = elg_fingerprint_md(pkc); + dp = md_read( md, DIGEST_ALGO_SHA1 ); + } array = m_alloc( 20 ); len = 20; memcpy(array, dp, 20 ); diff --git a/g10/keylist.c b/g10/keylist.c index 25573663a..3d209ecf8 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -107,6 +107,7 @@ list_one( const char *name ) goto leave; } + /* get the keyid from the keyblock */ node = find_kbnode( keyblock, PKT_PUBLIC_CERT ); if( !node ) { diff --git a/g10/main.h b/g10/main.h index 5078e80aa..c162fd9cd 100644 --- a/g10/main.h +++ b/g10/main.h @@ -113,4 +113,7 @@ int decrypt_message( const char *filename ); /*-- plaintext.c --*/ int hash_datafiles( MD_HANDLE md, STRLIST files, int textmode ); +/*-- signal.c --*/ +void init_signals(void); + #endif /*G10_MAIN_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index 3ca23ccc0..b5ceecef8 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -706,7 +706,7 @@ check_sig_and_print( CTX c, KBNODE node ) log_info("%s signature from ", rc? "BAD":"Good"); print_keyid( stderr, sig->keyid ); putc('\n', stderr); - if( opt.batch ) + if( opt.batch && rc ) g10_exit(1); } else { diff --git a/g10/packet.h b/g10/packet.h index 53448bd8e..5f29b83e5 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -50,6 +50,7 @@ typedef struct packet_struct PACKET; typedef struct { u32 keyid[2]; /* 64 bit keyid */ + 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 0cc2ece01..4281ef173 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -425,7 +425,6 @@ skip_rest( IOBUF inp, unsigned long pktlen ) static int parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) { - int version; unsigned n; PKT_pubkey_enc *k; @@ -434,17 +433,17 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) log_error("packet(%d) too short\n", pkttype); goto leave; } - version = iobuf_get_noeof(inp); pktlen--; - if( version != 2 && version != 3 ) { - log_error("packet(%d) with unknown version %d\n", pkttype, version); + k->version = iobuf_get_noeof(inp); pktlen--; + if( k->version != 2 && k->version != 3 ) { + log_error("packet(%d) with unknown version %d\n", pkttype, k->version); goto leave; } k->keyid[0] = read_32(inp); pktlen -= 4; k->keyid[1] = read_32(inp); pktlen -= 4; k->pubkey_algo = iobuf_get_noeof(inp); pktlen--; if( list_mode ) - printf(":public key encoded packet: keyid %08lX%08lX\n", - (ulong)k->keyid[0], (ulong)k->keyid[1]); + printf(":public key encoded packet: version %d, keyid %08lX%08lX\n", + k->version, (ulong)k->keyid[0], (ulong)k->keyid[1]); if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { n = pktlen; k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n; @@ -791,7 +790,10 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen, if( list_mode ) printf(":%s key packet:\n" "\tversion %d, created %lu, valid for %hu days\n", - pkttype == PKT_PUBLIC_CERT? "public": "secret", + pkttype == PKT_PUBLIC_CERT? "public" : + pkttype == PKT_SECRET_CERT? "secret" : + pkttype == PKT_PUBKEY_SUBCERT? "public sub" : + pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??", version, timestamp, valid_period ); if( pkttype == PKT_SECRET_CERT ) { pkt->pkt.secret_cert->timestamp = timestamp; diff --git a/g10/ringedit.c b/g10/ringedit.c index 1ec35b811..49e46ecde 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -78,7 +78,7 @@ 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_enum( KBPOS *kbpos, KBNODE *ret_root ); +static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); @@ -346,11 +346,13 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root ) * Mode is: 0 = open * 1 = read * 2 = close + * 5 = open secret keyrings + * 11 = read but skip signature and comment packets. * all others are reserved! - * Note that you do not need a search prior to call this function, - * only handle is needed. - * NOTE: It is not alloed to do an insert/update/delte with this - * keyblock, if you want to do this, user search/read! + * Note that you do not need a search prior to this function, + * only a handle is needed. + * NOTE: It is not allowed to do an insert/update/delte with this + * keyblock, if you want to do this, use search/read! */ int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) @@ -358,15 +360,23 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) int rc = 0; RESTBL *rentry; - if( !mode || mode == 100 ) { + if( !mode || mode == 5 || mode == 100 ) { int i; kbpos->fp = NULL; - if( !mode ) + if( !mode ) { + kbpos->secret = 0; i = 0; + } + else if( mode == 5 ) { + kbpos->secret = 1; + mode = 0; + i = 0; + } else i = kbpos->resno+1; for(; i < MAX_RESOURCES; i++ ) - if( resource_table[i].used && !resource_table[i].secret ) + if( resource_table[i].used + && !resource_table[i].secret == !kbpos->secret ) break; if( i == MAX_RESOURCES ) return -1; /* no resources */ @@ -379,13 +389,13 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) } kbpos->pkt = NULL; } - else if( mode == 1 ) { + else if( mode == 1 || mode == 11 ) { int cont; do { cont = 0; if( !kbpos->fp ) return G10ERR_GENERAL; - rc = keyring_enum( kbpos, ret_root ); + rc = keyring_enum( kbpos, ret_root, mode == 11 ); if( rc == -1 ) { assert( !kbpos->pkt ); rentry = check_pos( kbpos ); @@ -703,13 +713,12 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root ) static int -keyring_enum( KBPOS *kbpos, KBNODE *ret_root ) +keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ) { PACKET *pkt; int rc; RESTBL *rentry; KBNODE root = NULL; - int in_cert = 0; if( !(rentry=check_pos(kbpos)) ) return G10ERR_GENERAL; @@ -736,17 +745,28 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root ) switch( pkt->pkttype ) { case PKT_PUBLIC_CERT: case PKT_SECRET_CERT: - if( in_cert ) { /* store this packet */ + if( root ) { /* store this packet */ kbpos->pkt = pkt; pkt = NULL; goto ready; } - in_cert = 1; + root = new_kbnode( pkt ); + pkt = m_alloc( sizeof *pkt ); + init_packet(pkt); + break; + default: - if( !root ) - root = new_kbnode( pkt ); - else - add_kbnode( root, new_kbnode( pkt ) ); + /* skip pakets at the begin of a keyring, until we find + * a start packet; issue a warning if it is not a comment */ + if( !root && pkt->pkttype != PKT_COMMENT ) + log_info("keyring_enum: skipped packet of type %d\n", + pkt->pkttype ); + if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE + ||pkt->pkttype == PKT_COMMENT )) ) { + init_packet(pkt); + break; + } + add_kbnode( root, new_kbnode( pkt ) ); pkt = m_alloc( sizeof *pkt ); init_packet(pkt); break; diff --git a/g10/sig-check.c b/g10/sig-check.c index f25f2e19f..27e166ace 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -63,6 +63,10 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) MPI result = NULL; int rc=0; + + if( pkc->timestamp > sig->timestamp ) + return G10ERR_TIME_CONFLICT; /* pubkey newer that signature */ + if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { ELG_public_key pkey; @@ -96,8 +100,6 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) * signature */ md_enable( digest, sig->digest_algo ); - assert( sig->digest_algo == DIGEST_ALGO_SHA1 ); - /* complete the digest */ if( sig->version >= 4 ) md_putc( digest, sig->version ); @@ -117,10 +119,10 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) if( sig->hashed_data ) { n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; md_write( digest, sig->hashed_data, n+2 ); - n += 4; + n += 6; } else - n = 4; + n = 6; /* add some magic */ buf[0] = sig->version; buf[1] = 0xff; @@ -131,8 +133,10 @@ do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest ) md_write( digest, buf, 6 ); } md_final( digest ); - log_hexdump("digest is: ", md_read(digest, DIGEST_ALGO_SHA1), 20); - result = encode_md_value( digest, mpi_get_nbits(pkc->d.dsa.p)); + result = mpi_alloc( (md_digest_length(sig->digest_algo) + +BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB ); + mpi_set_buffer( result, md_read(digest, DIGEST_ALGO_SHA1), + md_digest_length(sig->digest_algo), 0 ); pkey.p = pkc->d.dsa.p; pkey.q = pkc->d.dsa.q; pkey.g = pkc->d.dsa.g; @@ -288,13 +292,11 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) keyid_from_pkc( pkc, keyid ); md = md_open( algo, 0 ); - if( sig->sig_class== 16 ) - md->debug = fopen("dsahashsig","w"); hash_public_cert( md, pkc ); if( sig->version >=4 ) { byte buf[5]; buf[0] = 0xb4; /* indicates a userid packet */ - buf[1] = uid->len >> 24; /* but use 4 length bytes */ + buf[1] = uid->len >> 24; /* always use 4 length bytes */ buf[2] = uid->len >> 16; buf[3] = uid->len >> 8; buf[4] = uid->len; @@ -309,8 +311,6 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig ) else rc = signature_check( sig, md ); md_close(md); - if( sig->sig_class== 16 ) - fclose(md->debug); } else { log_error("no user id for key signature packet\n"); diff --git a/g10/sign.c b/g10/sign.c index 4cf7b7bd6..fffee0870 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -871,8 +871,8 @@ delete_key( const char *username, int secret ) KBNODE keyblock = NULL; KBNODE node; KBPOS kbpos; - PKT_public_cert *pkc; - PKT_secret_cert *skc; + PKT_public_cert *pkc = NULL; + PKT_secret_cert *skc = NULL; u32 keyid[2]; int okay=0; diff --git a/g10/signal.c b/g10/signal.c new file mode 100644 index 000000000..9d57b6258 --- /dev/null +++ b/g10/signal.c @@ -0,0 +1,74 @@ +/* signal.c - signal handling + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG 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. + * + * GNUPG 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 <signal.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#include "options.h" +#include "errors.h" +#include "memory.h" +#include "util.h" +#include "main.h" +#include "ttyio.h" + + + +static RETSIGTYPE +print_and_exit( int sig ) +{ + const char *p; + + /* Hmm, use only safe functions (we should do an autoconf test) */ + write( 2, "\nCaught ", 8 ); + #if SYS_SIGLIST_DECLARED + p = sys_siglist[sig]; + write( 2, p, strlen(p) ); + #else + write( 2, "a signal", 8 ); + #endif + write( 2, "... exiting\n", 12 ); + secmem_term(); + exit(2); /* not correct but .. */ +} + + +void +init_signals() +{ + #if 0 + struct sigaction nact; + + nact.sa_handler = print_and_exit; + sigemptyset (&nact.sa_mask); + nact.sa_flags = 0; + + sigaction( SIGINT, &nact, NULL ); + sigaction( SIGHUP, &nact, NULL ); + sigaction( SIGTERM, &nact, NULL ); + #endif +} + + diff --git a/g10/trustdb.c b/g10/trustdb.c index 257c37204..9bea383c7 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -1388,8 +1388,8 @@ propagate_trust( TRUST_SEG_LIST tslist ) /**************** - * we have the pubkey record but nothing more is known - * function may re-read dr. + * we have the pubkey record but nothing more is known. + * (function may re-read dr) */ static int do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel ) @@ -1736,7 +1736,11 @@ check_trust( PKT_public_cert *pkc, unsigned *r_trustlevel ) pkc->local_id ); } } - /* fixme: do some additional checks on the pubkey record */ + if( pkc->timestamp > make_timestamp() ) { + log_info("public key created in future (time warp or clock problem)\n"); + return G10ERR_TIME_CONFLICT; + } + rc = do_check( pkc->local_id, &rec, &trustlevel ); if( rc ) { |