diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 32 | ||||
-rw-r--r-- | g10/OPTIONS | 13 | ||||
-rw-r--r-- | g10/armor.c | 27 | ||||
-rw-r--r-- | g10/g10.c | 32 | ||||
-rw-r--r-- | g10/getkey.c | 4 | ||||
-rw-r--r-- | g10/keydb.h | 8 | ||||
-rw-r--r-- | g10/keyedit.c | 4 | ||||
-rw-r--r-- | g10/keygen.c | 6 | ||||
-rw-r--r-- | g10/keyid.c | 24 | ||||
-rw-r--r-- | g10/keylist.c | 4 | ||||
-rw-r--r-- | g10/main.h | 4 | ||||
-rw-r--r-- | g10/mainproc.c | 27 | ||||
-rw-r--r-- | g10/misc.c | 22 | ||||
-rw-r--r-- | g10/openfile.c | 2 | ||||
-rw-r--r-- | g10/options.h | 1 | ||||
-rw-r--r-- | g10/packet.h | 2 | ||||
-rw-r--r-- | g10/pkclist.c | 8 | ||||
-rw-r--r-- | g10/plaintext.c | 45 | ||||
-rw-r--r-- | g10/seskey.c | 1 | ||||
-rw-r--r-- | g10/sign.c | 2 | ||||
-rw-r--r-- | g10/tdbio.c | 234 | ||||
-rw-r--r-- | g10/tdbio.h | 70 | ||||
-rw-r--r-- | g10/trustdb.c | 255 | ||||
-rw-r--r-- | g10/verify.c | 2 |
24 files changed, 547 insertions, 282 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index a637ac9e9..f6f935a57 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,35 @@ +Tue Jul 14 18:09:51 1998 Werner Koch ([email protected]) + + * keyid.c (fingerprint_from_pk): Add argument and changed all callers. + (fingerprint_from_sk): Ditto. + +Tue Jul 14 10:10:03 1998 Werner Koch ([email protected]) + + * plaintext.c (handle_plaintext): Now returns create error if + the file could not be created or the user responded not to overwrite + the file. + * mainproc.c (proc_plaintext): Tries again if the file could not + be created to check the signature without output. + + * misc.c (disable_core_dumps): New. + * g10.c (main): disable coredumps for gpg + + * g10.c (MAINTAINER_OPTIONS): New to disable some options + +Mon Jul 13 16:47:54 1998 Werner Koch ([email protected]) + + * plaintext.c (hash_datafiles): New arg for better support of + detached sigs. Changed all callers. + * mainproc.c (proc_signature_packets): Ditto. + + * g10.c (main): New option "compress-sigs" + * sig.c (sign_file): detached signatures are not anymore compressed + unless the option --compress-sigs is used. + +Thu Jul 9 19:54:54 1998 Werner Koch ([email protected]) + + * armor.c: Fixes to allow zero length cleartext signatures + Thu Jul 9 14:52:47 1998 Werner Koch ([email protected]) * g10.c (build_list): Now drops setuid. diff --git a/g10/OPTIONS b/g10/OPTIONS index 3abe296d8..8e9cf8a6c 100644 --- a/g10/OPTIONS +++ b/g10/OPTIONS @@ -17,15 +17,7 @@ #----------------------------------------------- #------------------- Commands ------------------ #----------------------------------------------- -# With some expections, these cannot be combined - -gen-prime -# Generate a prime. -# With one argument: take it as the bitsize and make a simple prime of -# this size -# With two arguments: Generate a prime, usable for DL algorithms. -# With three arguments: same as above, but a third argument indicates -# that a generator should also be calculated. +# With some exceptions, these cannot be combined print-md algo # print the message digest of algorithm ALGO for stdin or all @@ -53,4 +45,7 @@ compress-keys # algorithm with --compress-algo" - Default is to not compress keys, as # this is better for interoperability. +compress-sigs +# Normally, compressing of signatures does not make sense; so this +# is disabled for detached signatures unless this option is used. diff --git a/g10/armor.c b/g10/armor.c index 46151eae8..45f962f01 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -62,6 +62,7 @@ typedef enum { fhdrSKIPHeader, fhdrCLEARSIG, fhdrREADClearsig, + fhdrNullClearsig, fhdrEMPTYClearsig, fhdrCHECKClearsig, fhdrCHECKClearsig2, @@ -343,6 +344,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, *r_hashes |= hashes; } } + else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) ) + state = fhdrNullClearsig; else state = fhdrCHECKDashEscaped3; } @@ -386,7 +389,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, buf[n++] = c; if( n < buflen || c == '\n' ) { buf[n] = 0; - state = fhdrCHECKDashEscaped3; + if( n > 15 && !memcmp(buf, "-----", 5 ) ) + state = fhdrNullClearsig; + else + state = fhdrCHECKDashEscaped3; } else { /* fixme: we should check whether this line continues @@ -396,6 +402,10 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, } break; + case fhdrNullClearsig: /* zero length cleartext */ + state = fhdrENDClearsig; + break; + case fhdrENDClearsig: case fhdrCHECKBegin: state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow; @@ -587,10 +597,8 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen, buf[1] = '\n'; n = 2; } - } - *r_buflen = n; *r_empty = empty; return state; @@ -627,6 +635,7 @@ check_input( armor_filter_context_t *afx, IOBUF a ) rc = -1; break; + case fhdrNullClearsig: case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */ afx->helplen = n; afx->helpidx = 0; @@ -679,7 +688,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, rc = -1; continue; } - if( afx->helpidx < afx->helplen ) { /* flush the last buffer */ + if( state != fhdrNullClearsig + && afx->helpidx < afx->helplen ) { /* flush the last buffer */ n = afx->helplen; for(nn=afx->helpidx; len < size && nn < n ; nn++ ) buf[len++] = afx->helpbuf[nn]; @@ -693,7 +703,8 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, /* read a new one */ n = DIM(afx->helpbuf); afx->helpidx = 0; - state = find_header( state, afx->helpbuf, &n, a, 0, + state = find_header( state, afx->helpbuf, &n, a, + state == fhdrNullClearsig? afx->helplen:0, &emplines, &afx->hashes ); switch( state) { case fhdrERROR: @@ -723,8 +734,10 @@ fake_packet( armor_filter_context_t *afx, IOBUF a, buf[0] = (len-2) >> 8; buf[1] = (len-2); if( state == fhdrENDClearsig ) { /* write last (ending) length header */ - buf[len++] = 0; - buf[len++] = 0; + if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */ + buf[len++] = 0; + buf[len++] = 0; + } rc = 0; } @@ -25,6 +25,7 @@ #include <string.h> #include <unistd.h> +/* #define MAINTAINER_OPTIONS */ #include "packet.h" #include "iobuf.h" @@ -85,8 +86,10 @@ static ARGPARSE_OPTS opts[] = { { 547, "enarmor", 0, N_("En-Armor a file or stdin") }, { 555, "print-md" , 0, N_("|algo [files]|print message digests")}, { 516, "print-mds" , 0, N_("print all message digests")}, + #ifdef MAINTAINER_OPTIONS { 513, "gen-prime" , 0, "@" }, { 548, "gen-random" , 0, "@" }, + #endif #endif { 301, NULL, 0, N_("@\nOptions:\n ") }, @@ -165,6 +168,7 @@ static ARGPARSE_OPTS opts[] = { { 508, "check-sig",0, "@" }, /* alias */ { 553, "skip-verify",0, "@" }, { 557, "compress-keys",0, "@"}, + { 566, "compress-sigs",0, "@"}, { 559, "always-trust", 0, "@"}, { 562, "emulate-checksum-bug", 0, "@"}, @@ -413,6 +417,7 @@ main( int argc, char **argv ) */ log_set_name("gpg"); secure_random_alloc(); /* put random number into secure memory */ + disable_core_dumps(); init_signals(); #endif i18n_init(); @@ -529,15 +534,17 @@ main( int argc, char **argv ) #endif /* !IS_G10 */ #ifdef IS_G10MAINT - case 513: set_cmd( &cmd, aPrimegen); break; - case 514: set_cmd( &cmd, aTest); break; + #ifdef MAINTAINER_OPTIONS + case 513: set_cmd( &cmd, aPrimegen); break; + case 514: set_cmd( &cmd, aTest); break; + case 548: set_cmd( &cmd, aGenRandom); break; + #endif case 516: set_cmd( &cmd, aPrintMDs); break; case 531: set_cmd( &cmd, aListTrustDB); break; case 533: set_cmd( &cmd, aListTrustPath); break; case 540: break; /* dummy */ case 546: set_cmd( &cmd, aDeArmor); break; case 547: set_cmd( &cmd, aEnArmor); break; - case 548: set_cmd( &cmd, aGenRandom); break; case 555: set_cmd( &cmd, aPrintMD); break; case 564: set_cmd( &cmd, aListOwnerTrust); break; #endif /* IS_G10MAINT */ @@ -596,6 +603,7 @@ main( int argc, char **argv ) case 562: opt.emulate_bugs |= 1; break; case 563: set_cmd( &cmd, aExportSecret); break; case 565: opt.do_not_export_rsa = 1; break; + case 566: opt.compress_sigs = 1; break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -725,16 +733,16 @@ main( int argc, char **argv ) if( argc > 1 ) wrong_args(_("--store [filename]")); if( (rc = encode_store(fname)) ) - log_error("%s: store failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); + log_error_f( print_fname_stdin(fname), + "store failed: %s\n", g10_errstr(rc) ); break; #ifdef IS_G10 case aSym: /* encrypt the given file only with the symmetric cipher */ if( argc > 1 ) wrong_args(_("--symmetric [filename]")); if( (rc = encode_symmetric(fname)) ) - log_error("%s: symmetric encryption failed: %s\n", - print_fname_stdin(fname), g10_errstr(rc) ); + log_error_f(print_fname_stdin(fname), + "symmetric encryption failed: %s\n",g10_errstr(rc) ); break; case aEncr: /* encrypt the given file */ @@ -933,6 +941,7 @@ main( int argc, char **argv ) break; + #ifdef MAINTAINER_OPTIONS case aPrimegen: if( argc == 1 ) { mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1); @@ -960,7 +969,9 @@ main( int argc, char **argv ) else usage(1); break; + #endif /* MAINTAINER OPTIONS */ + #ifdef MAINTAINER_OPTIONS case aGenRandom: if( argc < 1 || argc > 2 ) wrong_args("--gen-random level [hex]"); @@ -977,6 +988,7 @@ main( int argc, char **argv ) } } break; + #endif /* MAINTAINER OPTIONS */ case aPrintMD: if( argc < 1) @@ -1007,7 +1019,9 @@ main( int argc, char **argv ) } break; + #ifdef MAINTAINER_OPTIONS case aTest: do_test( argc? atoi(*argv): 1 ); break; + #endif /* MAINTAINER OPTIONS */ case aListTrustDB: if( !argc ) @@ -1085,7 +1099,7 @@ do_not_use_RSA() if( !did_rsa_note ) { did_rsa_note = 1; - log_info(_("RSA keys are depreciated; please consider " + log_info(_("RSA keys are deprecated; please consider " "creating a new key and use this key in the future\n")); } } @@ -1194,10 +1208,12 @@ print_mds( const char *fname, int algo ) +#ifdef MAINTAINER_OPTIONS static void do_test(int times) { m_check(NULL); } +#endif /* MAINTAINER OPTIONS */ #endif /* IS_G10MAINT */ diff --git a/g10/getkey.c b/g10/getkey.c index 3f8ac63b8..b73a00616 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -758,7 +758,7 @@ lookup( PKT_public_key *pk, int mode, u32 *keyid, else if( mode == 16 || mode == 20 ) { size_t an; byte *afp = fingerprint_from_pk( - k->pkt->pkt.public_key, &an ); + k->pkt->pkt.public_key, NULL, &an ); if( DBG_CACHE ) { u32 aki[2]; @@ -897,7 +897,7 @@ lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name ) else if( mode == 16 || mode == 20 ) { size_t an; byte *afp = fingerprint_from_sk( - k->pkt->pkt.secret_key, &an ); + k->pkt->pkt.secret_key, NULL, &an ); if( an == mode && !memcmp( afp, name, an) && ( !sk->pubkey_algo || sk->pubkey_algo diff --git a/g10/keydb.h b/g10/keydb.h index 58a170d27..a0398092a 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -25,6 +25,7 @@ #include "packet.h" #include "cipher.h" +#define MAX_FINGERPRINT_LEN 20 /**************** @@ -80,11 +81,12 @@ struct pubkey_find_info { u32 keyid[2]; unsigned nbits; byte pubkey_algo; - byte fingerprint[20]; + byte fingerprint[MAX_FINGERPRINT_LEN]; char userid[1]; }; + /*-- pkclist.c --*/ int check_signatures_trust( PKT_signature *sig ); void release_pk_list( PK_LIST pk_list ); @@ -128,8 +130,8 @@ unsigned nbits_from_sk( PKT_secret_key *sk ); const char *datestr_from_pk( PKT_public_key *pk ); const char *datestr_from_sk( PKT_secret_key *sk ); const char *datestr_from_sig( PKT_signature *sig ); -byte *fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len ); -byte *fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len ); +byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf. size_t *ret_len ); +byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len ); /*-- kbnode.c --*/ KBNODE new_kbnode( PACKET *pkt ); diff --git a/g10/keyedit.c b/g10/keyedit.c index ee50a7880..4369e9a86 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -45,7 +45,7 @@ show_fingerprint( PKT_public_key *pk ) byte *array, *p; size_t i, n; - p = array = fingerprint_from_pk( pk, &n ); + p = array = fingerprint_from_pk( pk, NULL, &n ); tty_printf(" Fingerprint:"); if( n == 20 ) { for(i=0; i < n ; i++, i++, p += 2 ) { @@ -292,7 +292,7 @@ sign_key( const char *username, STRLIST locusr ) if( !opt.batch ) { /* ask whether we really should do anything */ answer = tty_get( - _("To you want to remove some of the invalid sigs? ")); + _("Do you want to remove some of the invalid signatures? ")); tty_kill_prompt(); if( answer_is_yes(answer) ) remove_keysigs( keyblock, pk_keyid, 0 ); diff --git a/g10/keygen.c b/g10/keygen.c index d9f8579e4..b114b8444 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -442,9 +442,9 @@ ask_keysize( int algo ) else if( nbits < 768 ) tty_printf(_("keysize too small; 768 is smallest value allowed.\n")); else if( nbits > 2048 ) { - tty_printf(_("Keysizes larger than 2048 are not suggested, because " + tty_printf(_("Keysizes larger than 2048 are not suggested because " "computations take REALLY long!\n")); - answer = tty_get(_("Are you sure, that you want this keysize? ")); + answer = tty_get(_("Are you sure that you want this keysize? ")); tty_kill_prompt(); if( answer_is_yes(answer) ) { m_free(answer); @@ -685,7 +685,7 @@ ask_passphrase( STRING2KEY **ret_s2k ) tty_printf(_( "You don't want a passphrase - this is probably a *bad* idea!\n" "I will do it anyway. You can change your passphrase at any time,\n" - "using this program with the option \"--change-passphrase\"\n\n")); + "using this program with the option \"--change-passphrase\".\n\n")); break; } else diff --git a/g10/keyid.c b/g10/keyid.c index 0809df93a..2e5c6aad6 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -262,13 +262,13 @@ datestr_from_sig( PKT_signature *sig ) /**************** . * Return a byte array with the fingerprint for the given PK/SK * The length of the array is returned in ret_len. Caller must free - * the array. + * the array or provide array as buffer of length MAX_FINGERPRINT_LEN */ byte * -fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len ) +fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) { - byte *p, *buf, *array; + byte *p, *buf; const char *dp; size_t len; unsigned n; @@ -287,7 +287,8 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len ) m_free(buf); } md_final(md); - array = m_alloc( 16 ); + if( !array ) + array = m_alloc( 16 ); len = 16; memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); md_close(md); @@ -297,7 +298,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len ) md = do_fingerprint_md(pk); dp = md_read( md, 0 ); len = md_digest_length( md_get_algo( md ) ); - array = m_alloc( len ); + assert( len <= MAX_FINGERPRINT_LEN ); + if( !array ) + array = m_alloc( len ); memcpy(array, dp, len ); md_close(md); } @@ -307,9 +310,9 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len ) } byte * -fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len ) +fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len ) { - byte *p, *buf, *array; + byte *p, *buf; const char *dp; size_t len; unsigned n; @@ -328,7 +331,8 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len ) m_free(buf); } md_final(md); - array = m_alloc( 16 ); + if( !array ) + array = m_alloc( 16 ); len = 16; memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 ); md_close(md); @@ -338,7 +342,9 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len ) md = do_fingerprint_md_sk(sk); dp = md_read( md, 0 ); len = md_digest_length( md_get_algo( md ) ); - array = m_alloc( len ); + assert( len <= MAX_FINGERPRINT_LEN ); + if( !array ) + array = m_alloc( len ); memcpy(array, dp, len ); md_close(md); } diff --git a/g10/keylist.c b/g10/keylist.c index f06b4989f..d23a98f1e 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -339,8 +339,8 @@ fingerprint( PKT_public_key *pk, PKT_secret_key *sk ) byte *array, *p; size_t i, n; - p = array = pk? fingerprint_from_pk( pk, &n ) - : fingerprint_from_sk( sk, &n ); + p = array = pk? fingerprint_from_pk( pk, NULL, &n ) + : fingerprint_from_sk( sk, NULL, &n ); if( opt.with_colons ) { printf("fpr:::::::::"); for(i=0; i < n ; i++, p++ ) diff --git a/g10/main.h b/g10/main.h index dcba0488f..fdb01343f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -47,6 +47,7 @@ void do_not_use_RSA(void); /*-- misc.c --*/ void trap_unaligned(void); +void disable_core_dumps(void); u16 checksum_u16( unsigned n ); u16 checksum( byte *p, unsigned n ); u16 checksum_mpi( MPI a ); @@ -119,7 +120,8 @@ int verify_signatures( int nfiles, char **files ); int decrypt_message( const char *filename ); /*-- plaintext.c --*/ -int hash_datafiles( MD_HANDLE md, STRLIST files, int textmode ); +int hash_datafiles( MD_HANDLE md, STRLIST files, const char *sigfilename, + int textmode ); /*-- signal.c --*/ void init_signals(void); diff --git a/g10/mainproc.c b/g10/mainproc.c index 9090fd4e1..cd3e85a8b 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -51,6 +51,7 @@ typedef struct { int sigs_only; /* process only signatures and reject all other stuff */ int encrypt_only; /* process only encrytion messages */ STRLIST signed_data; + const char *sigfilename; DEK *dek; int last_was_session_key; KBNODE list; /* the current list of packets */ @@ -262,7 +263,7 @@ proc_plaintext( CTX c, PACKET *pkt ) clearsig = 1; } } - if( !any ) { /* no onepass sig packet: enable all algos */ + if( !any ) { /* no onepass sig packet: enable all standard algos */ md_enable( c->mfx.md, DIGEST_ALGO_RMD160 ); md_enable( c->mfx.md, DIGEST_ALGO_SHA1 ); md_enable( c->mfx.md, DIGEST_ALGO_MD5 ); @@ -273,13 +274,13 @@ proc_plaintext( CTX c, PACKET *pkt ) m_check( c->mfx.md->list ); } rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig ); + if( rc == G10ERR_CREATE_FILE && !c->sigs_only) { + /* can't write output but we hash it anyway to + * check the signature */ + rc = handle_plaintext( pt, &c->mfx, 1, clearsig ); + } if( rc ) log_error( "handle plaintext failed: %s\n", g10_errstr(rc)); - if( c->mfx.md ) { - m_check(c->mfx.md); - if( c->mfx.md->list ) - m_check( c->mfx.md->list ); - } free_packet(pkt); c->last_was_session_key = 0; } @@ -288,7 +289,8 @@ proc_plaintext( CTX c, PACKET *pkt ) static int proc_compressed_cb( IOBUF a, void *info ) { - return proc_signature_packets( a, ((CTX)info)->signed_data ); + return proc_signature_packets( a, ((CTX)info)->signed_data, + ((CTX)info)->sigfilename ); } static int @@ -405,8 +407,8 @@ print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk ) byte *array, *p; size_t i, n; - p = array = sk? fingerprint_from_sk( sk, &n ) - : fingerprint_from_pk( pk, &n ); + p = array = sk? fingerprint_from_sk( sk, NULL, &n ) + : fingerprint_from_pk( pk, NULL, &n ); if( opt.with_colons ) { printf("fpr:::::::::"); for(i=0; i < n ; i++, p++ ) @@ -665,12 +667,13 @@ proc_packets( IOBUF a ) } int -proc_signature_packets( IOBUF a, STRLIST signedfiles ) +proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfilename ) { CTX c = m_alloc_clear( sizeof *c ); int rc; c->sigs_only = 1; c->signed_data = signedfiles; + c->sigfilename = sigfilename; rc = do_proc_packets( c, a ); m_free( c ); return rc; @@ -881,7 +884,7 @@ proc_tree( CTX c, KBNODE node ) } /* ask for file and hash it */ if( c->sigs_only ) - rc = hash_datafiles( c->mfx.md, c->signed_data, + rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename, n1->pkt->pkt.onepass_sig->sig_class == 0x01 ); else rc = ask_for_detached_datafile( &c->mfx, @@ -902,7 +905,7 @@ proc_tree( CTX c, KBNODE node ) free_md_filter_context( &c->mfx ); c->mfx.md = md_open(sig->digest_algo, 0); if( c->sigs_only ) - rc = hash_datafiles( c->mfx.md, c->signed_data, + rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename, sig->sig_class == 0x01 ); else rc = ask_for_detached_datafile( &c->mfx, diff --git a/g10/misc.c b/g10/misc.c index 470307363..ec7c40a1a 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -22,10 +22,15 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <errno.h> #if defined(__linux__) && defined(__alpha__) #include <asm/sysinfo.h> #include <asm/unistd.h> #endif +#ifdef HAVE_SETRLIMIT + #include <sys/time.h> + #include <sys/resource.h> +#endif #include "util.h" #include "main.h" #include "options.h" @@ -70,6 +75,23 @@ trap_unaligned(void) #endif +void +disable_core_dumps() +{ + #ifdef HAVE_SETRLIMIT + struct rlimit limit; + + limit.rlim_cur = 0; + limit.rlim_max = 0; + if( setrlimit( RLIMIT_CORE, &limit ) ) + log_fatal("can't disable core dumps: %s\n", strerror(errno) ); + #else + log_info("WARNING: Program may create a core file!\n"); + #endif +} + + + u16 checksum_u16( unsigned n ) { diff --git a/g10/openfile.c b/g10/openfile.c index be2702b55..afa36b983 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -142,6 +142,8 @@ open_sigfile( const char *iname ) buf = m_strdup(iname); buf[len-4] = 0 ; a = iobuf_open( buf ); + if( opt.verbose ) + log_info("assuming signed data in '%s'\n", buf ); m_free(buf); } } diff --git a/g10/options.h b/g10/options.h index 0929be328..80a6539ec 100644 --- a/g10/options.h +++ b/g10/options.h @@ -47,6 +47,7 @@ struct { const char *homedir; int skip_verify; int compress_keys; + int compress_sigs; int always_trust; int rfc1991; unsigned emulate_bugs; /* bug emulation flags */ diff --git a/g10/packet.h b/g10/packet.h index 0cefd8d10..cef9afe5c 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -222,7 +222,7 @@ typedef enum { /*-- mainproc.c --*/ int proc_packets( IOBUF a ); -int proc_signature_packets( IOBUF a, STRLIST signedfiles ); +int proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfile ); int proc_encryption_packets( IOBUF a ); int list_packets( IOBUF a ); diff --git a/g10/pkclist.c b/g10/pkclist.c index 81e23c765..e509f0064 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -63,7 +63,7 @@ query_ownertrust( ulong lid ) return 0; } - tty_printf(_("No ownertrust defined for %lu:\n" + tty_printf(_("No owner trust defined for %lu:\n" "%4u%c/%08lX %s \""), lid, nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ), (ulong)keyid[1], datestr_from_pk( pk ) ); @@ -143,7 +143,7 @@ _("Could not find a valid trust path to the key. Let's see whether we\n" while( !(rc=enum_trust_web( &context, &lid )) ) { rc = get_ownertrust( lid, &trust ); if( rc ) - log_fatal("Ooops: couldn't get ownertrust for %lu\n", lid); + log_fatal("Ooops: couldn't get owner trust for %lu\n", lid); if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED || trust == TRUST_UNKNOWN ) { if( query_ownertrust( lid ) ) @@ -155,7 +155,7 @@ _("Could not find a valid trust path to the key. Let's see whether we\n" enum_trust_web( &context, NULL ); /* close */ if( !any ) - tty_printf(_("No ownertrust values changed.\n\n") ); + tty_printf(_("No owner trust values changed.\n\n") ); return rc? rc : any? 0:-1; } @@ -366,7 +366,7 @@ check_signatures_trust( PKT_signature *sig ) case TRUST_MARGINAL: write_status( STATUS_TRUST_MARGINAL ); log_info(_( - "WARNING: This key is not certified with enough trusted signatures!\n" + "WARNING: This key is not certified with sufficiently trusted signatures!\n" )); log_info(_( " It is not certain that the signature belongs to the owner.\n" diff --git a/g10/plaintext.c b/g10/plaintext.c index 8d7b2a97e..1a22ecdbd 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -109,14 +109,17 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, /* no filename or "-" given; write to stdout */ fp = stdout; } - else if( overwrite_filep( fname ) ) + else if( (rc=overwrite_filep( fname )) ) { + if( rc == -1 ) + rc = G10ERR_CREATE_FILE; goto leave; + } if( fp || nooutput ) ; else if( !(fp = fopen(fname,"wb")) ) { log_error("Error creating '%s': %s\n", fname, strerror(errno) ); - rc = G10ERR_WRITE_FILE; + rc = G10ERR_CREATE_FILE; goto leave; } @@ -245,20 +248,43 @@ ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname ) } +static void +do_hash( MD_HANDLE md, IOBUF fp, int textmode ) +{ + text_filter_context_t tfx; + int c; + + if( textmode ) { + memset( &tfx, 0, sizeof tfx); + iobuf_push_filter( fp, text_filter, &tfx ); + } + while( (c = iobuf_get(fp)) != -1 ) + md_putc(md, c ); +} + + /**************** * Hash the given files and append the hash to hash context md. * If FILES is NULL, hash stdin. */ int -hash_datafiles( MD_HANDLE md, STRLIST files, int textmode ) +hash_datafiles( MD_HANDLE md, STRLIST files, + const char *sigfilename, int textmode ) { IOBUF fp; STRLIST sl=NULL; - text_filter_context_t tfx; - int c; - if( !files ) + if( !files ) { + /* check whether we can opne the signed material */ + fp = open_sigfile( sigfilename ); + if( fp ) { + do_hash( md, fp, textmode ); + iobuf_close(fp); + return 0; + } + /* no we can't (no sigfile) - read signed stuff from stdin */ add_to_strlist( &sl, "-"); + } else sl = files; @@ -271,12 +297,7 @@ hash_datafiles( MD_HANDLE md, STRLIST files, int textmode ) free_strlist(sl); return G10ERR_OPEN_FILE; } - if( textmode ) { - memset( &tfx, 0, sizeof tfx); - iobuf_push_filter( fp, text_filter, &tfx ); - } - while( (c = iobuf_get(fp)) != -1 ) - md_putc(md, c ); + do_hash( md, fp, textmode ); iobuf_close(fp); } diff --git a/g10/seskey.c b/g10/seskey.c index 5b271a2d4..6e76d12db 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -86,6 +86,7 @@ encode_session_key( DEK *dek, unsigned nbits ) frame[n++] = 2; i = nframe - 6 - dek->keylen; assert( i > 0 ); + /* FIXME: replace the loop by a call to get_random_bits() */ for( ; i ; i-- ) { while( !(c = get_random_byte(1)) ) ; diff --git a/g10/sign.c b/g10/sign.c index 14dfe417e..6192d5987 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -226,7 +226,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, iobuf_push_filter( out, encrypt_filter, &efx ); } - if( opt.compress && !outfile ) { + if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) { if( old_style ) zfx.algo = 1; iobuf_push_filter( out, compress_filter, &zfx ); diff --git a/g10/tdbio.c b/g10/tdbio.c index d3b9a7221..425e51cbb 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -147,7 +147,7 @@ create_db( const char *fname ) fp =fopen( fname, "w" ); if( !fp ) log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) ); - fwrite_8( fp, 1 ); + fwrite_8( fp, 2 ); fwrite_8( fp, 'g' ); fwrite_8( fp, 'p' ); fwrite_8( fp, 'g' ); @@ -195,55 +195,67 @@ tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ) case RECTYPE_VER: fprintf(fp, "version\n"); break; case RECTYPE_DIR: - fprintf(fp, "dir keyid=%08lX, key=%lu, ctl=%lu, sig=%lu", - (ulong)rec->r.dir.keyid[1], - rec->r.dir.keyrec, rec->r.dir.ctlrec, rec->r.dir.sigrec ); - if( rec->r.dir.no_sigs == 1 ) + fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x", + rec->r.dir.lid, + rec->r.dir.keylist, + rec->r.dir.uidlist, + rec->r.dir.cacherec, + rec->r.dir.ownertrust ); + if( rec->r.dir.sigflag == 1 ) fputs(", (none)", fp ); - else if( rec->r.dir.no_sigs == 2 ) + else if( rec->r.dir.sigflag == 2 ) fputs(", (invalid)", fp ); - else if( rec->r.dir.no_sigs == 3 ) + else if( rec->r.dir.sigflag == 3 ) fputs(", (revoked)", fp ); - else if( rec->r.dir.no_sigs ) + else if( rec->r.dir.sigflag ) fputs(", (??)", fp ); putc('\n', fp); break; - case RECTYPE_KEY: fprintf(fp, - "key %08lX, own=%lu, ownertrust=%02x, fl=%d\n", - (ulong)rec->r.key.keyid[1], - rec->r.key.owner, rec->r.key.ownertrust, + case RECTYPE_KEY: + fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d\n", + rec->r.key.lid, + rec->r.key.next, + rec->r.key.pubkey_algo, rec->r.key.fingerprint_len ); break; case RECTYPE_UID: - if( !rec->r.uid.subtype ) - fprintf(fp, - "uid %02x%02x, owner=%lu, chain=%lu, pref=%lu, otr=%02x\n", - rec->r.uid.namehash[18], rec->r.uid.namehash[19], - rec->r.uid.owner, rec->r.uid.chain, (ulong)rec->r.uid.prefrec, - rec->r.uid.ownertrust ); - else - fprintf(fp, - "uid subtype%d, owner=%lu, chain=%lu\n", - rec->r.uid.subtype, rec->r.uid.owner, rec->r.uid.chain); + fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X\n", + rec->r.uid.lid, + rec->r.uid.next, + rec->r.uid.prefrec, + rec->r.uid.siglist, + rec->r.uid.namehash[18], rec->r.uid.namehash[19]); break; - case RECTYPE_CTL: fprintf(fp, "ctl\n"); + case RECTYPE_PREF: + fprintf(fp, "pref %lu, next=%lu\n", + rec->r.uid.lid, + rec->r.uid.next); break; case RECTYPE_SIG: - fprintf(fp, "sigrec, owner=%lu, chain=%lu\n", - rec->r.sig.owner, rec->r.sig.chain ); + fprintf(fp, "sig %lu, next=%lu\n", + rec->r.sig.lid, rec->r.sig.next ); for(i=any=0; i < SIGS_PER_RECORD; i++ ) { - if( rec->r.sig.sig[i].local_id ) { + if( rec->r.sig.sig[i].lid ) { if( !any ) { putc('\t', fp); any++; } - fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].local_id, - rec->r.sig.sig[i].flag ); + fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid, + rec->r.sig.sig[i].flag ); } } if( any ) putc('\n', fp); break; + case RECTYPE_CACH: + fprintf(fp, "cach\n"); + break; + case RECTYPE_HTBL: + fprintf(fp, "htbl\n"); + break; + case RECTYPE_HTBL: + fprintf(fp, "hlst\n"); + break; default: fprintf(fp, "%d (unknown)\n", rec->rectype ); break; @@ -287,8 +299,7 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) case 0: /* unused record */ break; case RECTYPE_VER: /* version record */ - /* g10 was the original name */ - if( memcmp(buf+1, "gpg", 3 ) && memcmp(buf+1, "g10", 3 ) ) { + if( memcmp(buf+1, "gpg", 3 ) ) { log_error_f( db_name, _("not a trustdb file\n") ); rc = G10ERR_TRUSTDB; } @@ -306,51 +317,60 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ) (ulong)recnum ); rc = G10ERR_TRUSTDB; } - if( rec->r.ver.version != 1 ) { + if( rec->r.ver.version != 2 ) { log_error_f( db_name, "invalid file version %d\n", rec->r.ver.version ); rc = G10ERR_TRUSTDB; } break; case RECTYPE_DIR: /*directory record */ - rec->r.dir.local_id = buftoulong(p); p += 4; - rec->r.dir.keyid[0] = buftou32(p); p += 4; - rec->r.dir.keyid[1] = buftou32(p); p += 4; - rec->r.dir.keyrec = buftoulong(p); p += 4; - rec->r.dir.ctlrec = buftoulong(p); p += 4; - rec->r.dir.sigrec = buftoulong(p); p += 4; - rec->r.dir.no_sigs = *p++; - if( rec->r.dir.local_id != recnum ) { - log_error_f( db_name, "dir local_id != recnum (%lu,%lu)\n", - (ulong)rec->r.dir.local_id, - (ulong)recnum ); + rec->r.dir.lid = buftoulong(p); p += 4; + rec->r.dir.keylist = buftoulong(p); p += 4; + rec->r.dir.uidlist = buftoulong(p); p += 4; + rec->r.dir.cacherec = buftoulong(p); p += 4; + rec->r.dir.ownertrust = *p++; + rec->r.dir.sigflag = *p++; + if( rec->r.dir.lid != recnum ) { + log_error_f( db_name, "dir LID != recnum (%lu,%lu)\n", + rec->r.dir.lid, (ulong)recnum ); rc = G10ERR_TRUSTDB; } break; case RECTYPE_KEY: /* public key record */ - rec->r.key.owner = buftoulong(p); p += 4; - rec->r.dir.keyid[0] = buftou32(p); p += 4; - rec->r.dir.keyid[1] = buftou32(p); p += 4; + rec->r.key.lid = buftoulong(p); p += 4; + rec->r.key.next = buftoulong(p); p += 4; + p += 8; rec->r.key.pubkey_algo = *p++; rec->r.key.fingerprint_len = *p++; if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 ) rec->r.key.fingerprint_len = 20; - memcpy( rec->r.key.fingerprint, p, 20); p += 20; - rec->r.key.ownertrust = *p++; + memcpy( rec->r.key.fingerprint, p, 20); break; - case RECTYPE_CTL: /* control record */ - rec->r.ctl.owner = buftoulong(p); p += 4; - memcpy(rec->r.ctl.blockhash, p, 20); p += 20; - rec->r.ctl.trustlevel = *p++; + case RECTYPE_UID: /* user id record */ + rec->r.uid.lid = buftoulong(p); p += 4; + rec->r.uid.next = buftoulong(p); p += 4; + rec->r.uid.prefrec = buftoulong(p); p += 4; + rec->r.uid.siglist = buftoulong(p); p += 4; + p += 2; + memcpy( rec->r.uid.namehash, p, 20); + break; + case RECTYPE_PREF: /* preference record */ + rec->r.pref.lid = buftoulong(p); p += 4; + rec->r.pref.next = buftoulong(p); p += 4; break; case RECTYPE_SIG: - rec->r.sig.owner = buftoulong(p); p += 4; - rec->r.sig.chain = buftoulong(p); p += 4; + rec->r.sig.lid = buftoulong(p); p += 4; + rec->r.sig.next = buftoulong(p); p += 4; for(i=0; i < SIGS_PER_RECORD; i++ ) { - rec->r.sig.sig[i].local_id = buftoulong(p); p += 4; + rec->r.sig.sig[i].lid = buftoulong(p); p += 4; rec->r.sig.sig[i].flag = *p++; } break; + case RECTYPE_CACH: /* cache record (FIXME)*/ + rec->r.cache.lid = buftoulong(p); p += 4; + memcpy(rec->r.cache.blockhash, p, 20); p += 20; + rec->r.cache.trustlevel = *p++; + break; default: log_error_f( db_name, "invalid record type %d at recnum %lu\n", rec->rectype, (ulong)recnum ); @@ -385,40 +405,53 @@ tdbio_write_record( ulong recnum, TRUSTREC *rec ) break; case RECTYPE_DIR: /*directory record */ - ulongtobuf(p, rec->r.dir.local_id); p += 4; - u32tobuf(p, rec->r.key.keyid[0]); p += 4; - u32tobuf(p, rec->r.key.keyid[1]); p += 4; - ulongtobuf(p, rec->r.dir.keyrec); p += 4; - ulongtobuf(p, rec->r.dir.ctlrec); p += 4; - ulongtobuf(p, rec->r.dir.sigrec); p += 4; - *p++ = rec->r.dir.no_sigs; - assert( rec->r.dir.local_id == recnum ); + ulongtobuf(p, rec->r.dir.lid); p += 4; + ulongtobuf(p, rec->r.dir.keylist); p += 4; + ulongtobuf(p, rec->r.dir.uidlist); p += 4; + ulongtobuf(p, rec->r.dir.cacherec); p += 4; + *p++ = rec->r.dir.ownertrust; + *p++ = rec->r.dir.sigflag; + assert( rec->r.dir.lid == recnum ); break; case RECTYPE_KEY: - ulongtobuf(p, rec->r.key.owner); p += 4; - u32tobuf(p, rec->r.key.keyid[0]); p += 4; - u32tobuf(p, rec->r.key.keyid[1]); p += 4; + ulongtobuf(p, rec->r.key.lid); p += 4; + ulongtobuf(p, rec->r.key.next); p += 4; + p += 8; *p++ = rec->r.key.pubkey_algo; *p++ = rec->r.key.fingerprint_len; memcpy( p, rec->r.key.fingerprint, 20); p += 20; - *p++ = rec->r.key.ownertrust; break; - case RECTYPE_CTL: /* control record */ - ulongtobuf(p, rec->r.ctl.owner); p += 4; - memcpy(p, rec->r.ctl.blockhash, 20); p += 20; - *p++ = rec->r.ctl.trustlevel; + case RECTYPE_UID: /* user id record */ + ulongtobuf(p, rec->r.uid.lid); p += 4; + ulongtobuf(p, rec->r.uid.next); p += 4; + ulongtobuf(p, rec->r.uid.prefrec); p += 4; + ulongtobuf(p, rec->r.uid.siglist); p += 4; + p += 2; + memcpy( p, rec->r.uid.namehash, 20 ); p += 20; + break; + + case RECTYPE_PREF: + ulongtobuf(p, rec->r.pref.lid); p += 4; + ulongtobuf(p, rec->r.pref.next); p += 4; break; case RECTYPE_SIG: - ulongtobuf(p, rec->r.sig.owner); p += 4; - ulongtobuf(p, rec->r.sig.chain); p += 4; + ulongtobuf(p, rec->r.sig.lid); p += 4; + ulongtobuf(p, rec->r.sig.next); p += 4; for(i=0; i < SIGS_PER_RECORD; i++ ) { - ulongtobuf(p, rec->r.sig.sig[i].local_id); p += 4; + ulongtobuf(p, rec->r.sig.sig[i].lid); p += 4; *p++ = rec->r.sig.sig[i].flag; } break; + + case RECTYPE_CACH: /* FIXME*/ + ulongtobuf(p, rec->r.cache.lid); p += 4; + memcpy(p, rec->r.cache.blockhash, 20); p += 20; + *p++ = rec->r.cache.trustlevel; + break; + default: BUG(); } @@ -475,7 +508,7 @@ tdbio_new_recnum() * Note: To increase performance, we could use a index search here. */ int -tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec ) +tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec ) { ulong recnum; u32 keyid[2]; @@ -484,30 +517,26 @@ tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec ) int rc; keyid_from_pk( pk, keyid ); - fingerprint = fingerprint_from_pk( pk, &fingerlen ); + fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen ); assert( fingerlen == 20 || fingerlen == 16 ); for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) { - if( rec->rectype != RECTYPE_DIR ) + if( rec->rectype != RECTYPE_KEY ) continue; - if( rec->r.dir.keyid[0] == keyid[0] - && rec->r.dir.keyid[1] == keyid[1]){ - TRUSTREC keyrec; - - if( tdbio_read_record( rec->r.dir.keyrec, &keyrec, RECTYPE_KEY ) ) { - log_error("%lu: ooops: invalid key record\n", recnum ); + if( rec->r.key.pubkey_algo == pk->pubkey_algo + && !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) { + /* found: read the dir record for this key */ + rc = tdbio_read_record( rec->r.key.lid, rec, RECTYPE_DIR); + if( rc ) break; - } - if( keyrec.r.key.pubkey_algo == pk->pubkey_algo - && !memcmp(keyrec.r.key.fingerprint, fingerprint, fingerlen) ){ - if( pk->local_id && pk->local_id != recnum ) - log_error_f(db_name, - "found record, but local_id from memory does " - "not match recnum (%lu,%lu)\n", - (ulong)pk->local_id, (ulong)recnum ); - pk->local_id = recnum; - return 0; - } + + if( pk->local_id && pk->local_id != recnum ) + log_error_f(db_name, + "found record, but LID from memory does " + "not match recnum (%lu,%lu)\n", + pk->local_id, recnum ); + pk->local_id = recnum; + return 0; } } if( rc != -1 ) @@ -516,3 +545,22 @@ tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec ) } +int +tdbio_update_sigflag( ulong lid, int sigflag ) +{ + TRUSTREC rec; + + if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { + log_error("update_sigflag: read failed\n"); + return G10ERR_TRUSTDB; + } + + rec.r.dir.sigflag = sigflag; + if( tdbio_write_record( lid, &rec ) ) { + log_error("update_sigflag: write failed\n"); + return G10ERR_TRUSTDB; + } + + return 0; +} + diff --git a/g10/tdbio.h b/g10/tdbio.h index facb5c307..7229d7222 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -32,15 +32,17 @@ #define RECTYPE_VER 1 #define RECTYPE_DIR 2 #define RECTYPE_KEY 3 -#define RECTYPE_CTL 4 -#define RECTYPE_SIG 5 -#define RECTYPE_HTBL 6 -#define RECTYPE_HLST 7 -#define RECTYPE_UID 8 +#define RECTYPE_UID 4 +#define RECTYPE_PREF 5 +#define RECTYPE_SIG 6 +#define RECTYPE_CACH 9 +#define RECTYPE_HTBL 10 +#define RECTYPE_HLST 11 struct trust_record { int rectype; + struct trust_record *next; union { struct { /* version record: */ byte version; /* should be 1 */ @@ -53,49 +55,50 @@ struct trust_record { byte max_cert_depth; } ver; struct { /* directory record */ - ulong local_id; - u32 keyid[2]; - ulong keyrec; /* recno of primary public key record */ - ulong ctlrec; /* recno of control record */ - ulong sigrec; /* recno of first signature record (osolete) */ - ulong uidrec; /* recno of first user-id record */ - ulong link; /* to next dir record */ - byte no_sigs; /* does not have sigature and checked */ + ulong lid; + ulong keylist; /* List of keys (the first is the primary key)*/ + ulong uidlist; /* list of uid records */ + ulong cacherec; /* the cache record */ + byte ownertrust; + byte sigflag; } dir; struct { /* primary public key record */ - ulong owner; - u32 keyid[2]; + ulong lid; + ulong next; /* next key */ byte pubkey_algo; byte fingerprint_len; byte fingerprint[20]; - byte ownertrust; } key; struct { /* user id reord */ - ulong owner; /* point back to the directory record */ - ulong chain; /* points to next user id record */ - byte subtype; /* must be 0 */ - byte namehash[20]; /* ripemd hash of the username */ - byte ownertrust; - u32 prefrec; /* recno of reference record */ + ulong lid; /* point back to the directory record */ + ulong next; /* points to next user id record */ + ulong prefrec; /* recno of reference record */ + ulong siglist; /* list of valid signatures (w/o self-sig)*/ + byte namehash[20]; /* ripemd hash of the username */ } uid; - struct { /* control record */ - ulong owner; - byte blockhash[20]; - byte trustlevel; /* calculated trustlevel */ - } ctl; + struct { /* preference reord */ + ulong lid; /* point back to the directory record */ + /* or 0 for a glocal pref record */ + ulong next; /* points to next pref record */ + } pref; struct { /* signature record */ - ulong owner; /* local_id of record owner (pubkey record) */ - ulong chain; /* offset of next record or NULL for last one */ + ulong lid; + ulong next; /* recnno of next record or NULL for last one */ struct { - ulong local_id; /* of pubkey record of signator (0=unused) */ - byte flag; /* reserved */ + ulong lid; /* of pubkey record of signator (0=unused) */ + byte flag; /* reserved */ } sig[SIGS_PER_RECORD]; } sig; + struct { /* cache record */ + ulong lid; + byte blockhash[20]; + byte trustlevel; /* calculated trustlevel */ + } cache; struct { ulong item[ITEMS_PER_HTBL_RECORD]; } htbl; struct { - ulong chain; + ulong next; struct { byte hash; ulong rnum; @@ -126,7 +129,8 @@ void tdbio_dump_record( ulong rnum, TRUSTREC *rec, FILE *fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( ulong recnum, TRUSTREC *rec ); ulong tdbio_new_recnum(void); -int tdbio_search_record( PKT_public_key *pk, TRUSTREC *rec ); +int tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec ); +int tdbio_update_sigflag( ulong lid, int sigflag ); #define buftoulong( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \ diff --git a/g10/trustdb.c b/g10/trustdb.c index 916eeffd1..593e12cd2 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -42,6 +42,10 @@ #include "tdbio.h" +#if MAX_FINGERPRINT_LEN > 20 + #error Must change structure of trustdb +#endif + typedef struct local_id_info *LOCAL_ID_INFO; struct local_id_info { LOCAL_ID_INFO next; @@ -85,11 +89,10 @@ static int do_list_path( TRUST_INFO *stack, int depth, int max_depth, LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ); static int list_sigs( ulong pubkey_id ); -static int build_sigrecs( ulong pubkeyid ); +static int build_sigrecs( ulong local_id ); static int propagate_trust( TRUST_SEG_LIST tslist ); -static int do_check( ulong pubkeyid, TRUSTREC *drec, unsigned *trustlevel ); +static int do_check( TRUSTREC *drec, unsigned *trustlevel ); -static int update_no_sigs( ulong lid, int no_sigs ); /* a table used to keep track of ultimately trusted keys * which are the ones from our secrings */ @@ -186,12 +189,11 @@ set_signature_packets_local_id( PKT_signature *sig ) if( rc) goto leave; if( !pk->local_id ) { - rc = tdbio_search_record( pk, &rec ); + rc = tdbio_search_dir_record( pk, &rec ); if( rc == -1 ) rc = insert_trust_record( pk ); if( rc ) goto leave; - /* fixme: we should propagate the local_id to all copies of the PK */ } sig->local_id = pk->local_id; @@ -666,35 +668,36 @@ check_sigs( KBNODE keyblock, int *selfsig_okay, int *revoked ) * to the trustdb */ static int -build_sigrecs( ulong pubkeyid ) +build_sigrecs( ulong lid ) { TRUSTREC rec, krec, rec2; - KBNODE keyblock = NULL; - KBNODE node; + KBNODE keyblock = NULL; + KBNODE node; int rc=0; int i, selfsig, revoked; ulong rnum, rnum2; ulong first_sigrec = 0; if( DBG_TRUST ) - log_debug("trustdb: build_sigrecs for pubkey %lu\n", (ulong)pubkeyid ); + log_debug("trustdb: build_sigrecs for LID %lu\n", lid ); /* get the keyblock */ - if( (rc=tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) { - log_error(_("%lu: build_sigrecs: can't read dir record\n"), pubkeyid ); + if( (rc=tdbio_read_record( lid, &rec, RECTYPE_DIR )) ) { + log_error( "build_sigrecs: can't read dir record %lu\n"), lid ); goto leave; } - if( (rc=tdbio_read_record( rec.r.dir.keyrec, &krec, RECTYPE_KEY )) ) { - log_error(_("%lu: build_sigrecs: can't read key record\n"), pubkeyid); + if( (rc=tdbio_read_record( rec.r.dir.keylist, &krec, RECTYPE_KEY )) ) { + log_error("build_sigrecs: can't read primary key record %lu\n"), lid); goto leave; } rc = get_keyblock_byfprint( &keyblock, krec.r.key.fingerprint, krec.r.key.fingerprint_len ); if( rc ) { - log_error(_("build_sigrecs: get_keyblock_byfprint failed: %s\n"), - g10_errstr(rc) ); + log_error( "build_sigrecs: keyblock for %lu not found: %s\n", + lid, g10_errstr(rc) ); goto leave; } + /* check all key signatures */ rc = check_sigs( keyblock, &selfsig, &revoked ); if( rc ) { @@ -703,19 +706,18 @@ build_sigrecs( ulong pubkeyid ) } if( !selfsig ) { log_error(_("build_sigrecs: self-signature missing\n") ); - update_no_sigs( pubkeyid, 2 ); + tdbio_update_sigflag( lid, 2 ); rc = G10ERR_BAD_CERT; goto leave; } if( revoked ) { log_info(_("build_sigrecs: key has been revoked\n") ); - update_no_sigs( pubkeyid, 3 ); + tdbio_update_sigflag( lid, 3 ); } else - update_no_sigs( pubkeyid, 0 ); /* assume we have sigs */ + tdbio_update_sigflag( lid, 0 ); /* assume we have sigs */ - /* valid key signatures are now marked; we can now build the - * sigrecs */ + /* valid key signatures are now marked; we can now build the sigrecs */ memset( &rec, 0, sizeof rec ); rec.rectype = RECTYPE_SIG; i = 0; @@ -740,8 +742,8 @@ build_sigrecs( ulong pubkeyid ) /* write the record */ rnum = tdbio_new_recnum(); if( rnum2 ) { /* write the stored record */ - rec2.r.sig.owner = pubkeyid; - rec2.r.sig.chain = rnum; /* the next record number */ + rec2.r.sig.lid = lid; + rec2.r.sig.next = rnum; /* the next record number */ rc = tdbio_write_record( rnum2, &rec2 ); if( rc ) { log_error(_("build_sigrecs: write_record failed\n") ); @@ -756,7 +758,7 @@ build_sigrecs( ulong pubkeyid ) rec.rectype = RECTYPE_SIG; i = 0; } - rec.r.sig.sig[i].local_id = node->pkt->pkt.signature->local_id; + rec.r.sig.sig[i].lid = node->pkt->pkt.signature->local_id; rec.r.sig.sig[i].flag = 0; i++; } @@ -765,8 +767,8 @@ build_sigrecs( ulong pubkeyid ) /* write the record */ rnum = tdbio_new_recnum(); if( rnum2 ) { /* write the stored record */ - rec2.r.sig.owner = pubkeyid; - rec2.r.sig.chain = rnum; + rec2.r.sig.lid = lid; + rec2.r.sig.next = rnum; rc = tdbio_write_record( rnum2, &rec2 ); if( rc ) { log_error(_("build_sigrecs: write_record failed\n") ); @@ -776,8 +778,8 @@ build_sigrecs( ulong pubkeyid ) first_sigrec = rnum2; } if( i ) { /* write the pending record */ - rec.r.sig.owner = pubkeyid; - rec.r.sig.chain = 0; + rec.r.sig.lid = lid; + rec.r.sig.next = 0; rc = tdbio_write_record( rnum, &rec ); if( rc ) { log_error(_("build_sigrecs: write_record failed\n") ); @@ -787,8 +789,7 @@ build_sigrecs( ulong pubkeyid ) first_sigrec = rnum; } } - if( first_sigrec ) { - /* update the dir record */ + if( first_sigrec ) { /* update the uid records */ if( (rc =tdbio_read_record( pubkeyid, &rec, RECTYPE_DIR )) ) { log_error(_("update_dir_record: read failed\n")); goto leave; @@ -800,7 +801,7 @@ build_sigrecs( ulong pubkeyid ) } } else - update_no_sigs( pubkeyid, revoked? 3:1 ); /* no signatures */ + tdbio_update_sigflag( lid, revoked? 3:1 ); /* no signatures */ leave: release_kbnode( keyblock ); @@ -900,12 +901,24 @@ propagate_trust( TRUST_SEG_LIST tslist ) } + /**************** - * we have the pubkey record but nothing more is known. - * (function may re-read dr) + * check whether we already build signature records + * Return: true if we have. */ static int -do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel ) +do_we_have_sigs( TRUSTREC *dr ) +{ +} + + +/**************** + * we have the pubkey record and all needed informations are in the trustdb + * but nothing more is known. + * (this function may re-read the dir record dr) + */ +static int +do_check( TRUSTREC *dr, unsigned *trustlevel ) { int i, rc=0; TRUST_SEG_LIST tsl, tsl2, tslist; @@ -919,16 +932,27 @@ do_check( ulong pubkeyid, TRUSTREC *dr, unsigned *trustlevel ) *trustlevel = TRUST_UNDEFINED; + if( !dr->r.dir.keylist ) { + log_error("Ooops, no keys\n"); + return G10ERR_TRUSTDB + } + if( !dr->r.dir.uidlist ) { + log_error("Ooops, no user ids\n"); + return G10ERR_TRUSTDB + } + /* verify the cache */ /* do we have sigrecs */ - if( !dr->r.dir.sigrec && !dr->r.dir.no_sigs) { - /* no sigrecs, so build them */ - rc = build_sigrecs( pubkeyid ); + if( !do_we_have_sigs( dr ) ) { /* no sigrecs, so build them */ + rc = build_sigrecs( dr->lid ); if( !rc ) /* and read again */ - rc = tdbio_read_record( pubkeyid, dr, RECTYPE_DIR ); + rc = tdbio_read_record( dr->lid, dr, RECTYPE_DIR ); } + + !!!!WORK!!!! + if( dr->r.dir.no_sigs == 3 ) tflags |= TRUST_FLAG_REVOKED; @@ -1199,9 +1223,7 @@ list_trust_path( int max_depth, const char *username ) * yes: return trustlevel from cache * no: make a cache record and all the other stuff * not found: - * Return with a trustlevel, saying that we do not have - * a trust record for it. The caller may use insert_trust_record() - * and then call this function here again. + * try to insert the pubkey into the trustdb and check again * * Problems: How do we get the complete keyblock to check that the * cache record is actually valid? Think we need a clever @@ -1225,17 +1247,17 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) /* get the pubkey record */ if( pk->local_id ) { if( tdbio_read_record( pk->local_id, &rec, RECTYPE_DIR ) ) { - log_error(_("check_trust: read dir record failed\n")); + log_error("check_trust: read dir record failed\n"); return G10ERR_TRUSTDB; } } else { /* no local_id: scan the trustdb */ - if( (rc=tdbio_search_record( pk, &rec )) && rc != -1 ) { - log_error(_("check_trust: search_record failed: %s\n"), + if( (rc=tdbio_search_dir_record( pk, &rec )) && rc != -1 ) { + log_error("check_trust: search dir record failed: %s\n", g10_errstr(rc)); return rc; } - else if( rc == -1 ) { + else if( rc == -1 ) { /* not found - insert */ rc = insert_trust_record( pk ); if( rc ) { log_error(_("key %08lX: insert trust record failed: %s\n"), @@ -1263,7 +1285,7 @@ check_trust( PKT_public_key *pk, unsigned *r_trustlevel ) trustlevel = TRUST_EXPIRED; } else { - rc = do_check( pk->local_id, &rec, &trustlevel ); + rc = do_check( &rec, &trustlevel ); if( rc ) { log_error(_("key %08lX.%lu: trust check failed: %s\n"), keyid[1], pk->local_id, g10_errstr(rc)); @@ -1424,24 +1446,119 @@ query_trust_record( PKT_public_key *pk ) * This function fails if this record already exists. */ int -insert_trust_record( PKT_public_key *pk ) +insert_trust_record( PKT_public_key *orig_pk ) { - TRUSTREC rec; + TRUSTREC dirrec, *rec; + TRUSTREC **keylist_tail, *keylist; + TRUSTREC **uidlist_tail, *uidlist; + KBNODE keyblock = NULL; + KBNODE node; u32 keyid[2]; ulong knum, dnum; byte *fingerprint; size_t fingerlen; + int rc = 0; - if( pk->local_id ) + if( orig_pk->local_id ) log_bug("pk->local_id=%lu\n", (ulong)pk->local_id ); - keyid_from_pk( pk, keyid ); - fingerprint = fingerprint_from_pk( pk, &fingerlen ); + fingerprint = fingerprint_from_pk( orig_pk, &fingerlen ); + + /* fixme: assert that we do not have this record. + * we can do this by searching for the primary keyid + */ + + /* get the keyblock which has the key */ + rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen ); + if( rc ) { /* that should never happen */ + log_error( "insert_trust_record: keyblock not found: %s\n", + g10_errstr(rc) ); + return rc; + } + + /* prepare dir record */ + memset( &dirrec, 0, sizeof dirrec ); + dirrec.rectype = RECTYPE_DIR; + dirrec.r.dir.lid = tdbio_new_recnum(); + + keylist = NULL; + keylist_tail = &dirrec.r.dir.keylist; + uidlist = NULL; + uidlist_tail = &dirrec.r.dir.uidlist; + /* loop over the keyblock */ + for( node=keyblock; node; node = node->next ) { + if( node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { + PKT_public_key *pk = node->pkt->pkt.public_key; + + if( keylist && node->pkt->pkttype == PKT_PUBLIC_KEY ) + BUG(); /* more than one primary key */ + fingerprint = fingerprint_from_pk( orig_pk, &fingerlen ); + rec = m_alloc_clear( sizeof *rec ); + rec->r.key.pubkey_algo = pk->pubkey_algo; + rec->r.key.fingerprint_len = fingerlen; + memcpy(rec->r.key.fingerprint, fingerprint, fingerlen ); + + if( keylist ) + keylist_tail = &keylist->next; + *keylist_tail = keylist = rec; + } + else if( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = node->pkt->pkt.user_id; + + rec = m_alloc_clear( sizeof *rec ); + rmd160_hash_buffer( rec->r.uid.namehash, uid->name, uid->len ); + + if( uidlist ) + uidlist_tail = &uidlist->next; + *uidlist_tail = uidlist = rec; + } + if( node->pkt->pkttype == PKT_SIGNATURE + && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10 + || node->pkt->pkt.signature->sig_class == 0x20 + || node->pkt->pkt.signature->sig_class == 0x30) ) { + int selfsig; + rc = check_key_signature( keyblock, node, &selfsig ); + if( !rc ) { + 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( selfsig ) { + node->flag |= 2; /* mark signature valid */ + *selfsig_okay = 1; + } + else if( node->pkt->pkt.signature->sig_class == 0x20 ) + *revoked = 1; + else + node->flag |= 1; /* mark signature valid */ + + if( node->pkt->pkt.signature->sig_class != 0x20 ) { + if( !dups ) + dups = new_lid_table(); + if( ins_lid_table_item( dups, + node->pkt->pkt.signature->local_id, 0) ) + node->flag |= 4; /* mark as duplicate */ + } + } + if( DBG_TRUST ) + log_debug("trustdb: sig from %08lX.%lu: %s%s\n", + (ulong)node->pkt->pkt.signature->keyid[1], + node->pkt->pkt.signature->local_id, + g10_errstr(rc), (node->flag&4)?" (dup)":"" ); + } + } + + + + + + + + - /* fixme: assert that we do not have this record. */ - dnum = tdbio_new_recnum(); knum = tdbio_new_recnum(); /* build dir record */ memset( &rec, 0, sizeof rec ); @@ -1451,10 +1568,6 @@ insert_trust_record( PKT_public_key *pk ) rec.r.dir.keyid[1] = keyid[1]; rec.r.dir.keyrec = knum; rec.r.dir.no_sigs = 0; - if( tdbio_write_record( dnum, &rec ) ) { - log_error("writing dir record failed\n"); - return G10ERR_TRUSTDB; - } /* and the key record */ memset( &rec, 0, sizeof rec ); rec.rectype = RECTYPE_KEY; @@ -1469,8 +1582,14 @@ insert_trust_record( PKT_public_key *pk ) log_error("wrinting key record failed\n"); return G10ERR_TRUSTDB; } + + if( tdbio_write_record( dirrec.r.dir.lid, &dirrec ) ) { + log_error("writing dir record failed\n"); + return G10ERR_TRUSTDB; + } + /* and store the LID */ - pk->local_id = dnum; + orig_pk->local_id = dnum; return 0; } @@ -1504,27 +1623,5 @@ update_ownertrust( ulong lid, unsigned new_trust ) -/**************** - * Kludge to prevent duplicate build_sigrecs() due to an invalid - * certificate (no selfsignature or something like this) - */ -static int -update_no_sigs( ulong lid, int no_sigs ) -{ - TRUSTREC rec; - - if( tdbio_read_record( lid, &rec, RECTYPE_DIR ) ) { - log_error("update_no_sigs: read failed\n"); - return G10ERR_TRUSTDB; - } - - rec.r.dir.no_sigs = no_sigs; - if( tdbio_write_record( lid, &rec ) ) { - log_error("update_no_sigs: write failed\n"); - return G10ERR_TRUSTDB; - } - - return 0; -} diff --git a/g10/verify.c b/g10/verify.c index 7a2f73130..02cc5d003 100644 --- a/g10/verify.c +++ b/g10/verify.c @@ -77,7 +77,7 @@ verify_signatures( int nfiles, char **files ) sl = NULL; for(i=1 ; i < nfiles; i++ ) add_to_strlist( &sl, files[i] ); - rc = proc_signature_packets( fp, sl ); + rc = proc_signature_packets( fp, sl, sigfile ); free_strlist(sl); iobuf_close(fp); return rc; |