From 3afe991bb88fe31c8f24d5c5ddd7621a6bbe258e Mon Sep 17 00:00:00 2001 From: David Shaw Date: Sat, 3 May 2003 04:07:45 +0000 Subject: [PATCH] * packet.h, build-packet.c (build_sig_subpkt), export.c (do_export_stream), import.c (remove_bad_stuff, import), parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt): Remove vestigal code for the old sig cache subpacket. This wasn't completely harmless as it caused subpacket 101 to disappear on import and export. * options.h, armor.c, cipher.c, g10.c, keyedit.c, pkclist.c, sign.c, encode.c, getkey.c, revoke.c: The current flags for different levels of PGP-ness are massively complex. This is step one in simplifying them. No functional change yet, just use a macro to check for compliance level. * sign.c (sign_file): Fix bug that causes spurious compression preference warning. * sign.c (clearsign_file): Fix bug that prevents proper warning message from appearing when clearsigning in --pgp2 mode with a non-v3 RSA key. * main.h, misc.c (compliance_option_string, compliance_string, compliance_failure), pkclist.c (build_pk_list), sign.c (sign_file, clearsign_file), encode.c (encode_crypt, write_pubkey_enc_from_list): New functions to put the "this message may not be usable...." warning in one place. * options.h, g10.c (main): Part two of the simplification. Use a single enum to indicate what we are compliant to (1991, 2440, PGPx, etc.) * g10.c (main): Show errors for failure in export, send-keys, recv-keys, and refresh-keys. * options.h, g10.c (main): Give algorithm warnings for algorithms chosen against the --pgpX and --openpgp rules. * keydb.h, pkclist.c (algo_available): Make TIGER192 invalid in --openpgp mode. * sign.c (sign_file), pkclist.c (algo_available): Allow passing a hint of 0. --- g10/ChangeLog | 44 +++++++ g10/armor.c | 4 +- g10/build-packet.c | 3 - g10/cipher.c | 2 +- g10/encode.c | 35 +++--- g10/export.c | 4 - g10/g10.c | 286 +++++++++++++++++++++++++++------------------ g10/getkey.c | 2 +- g10/import.c | 18 --- g10/keydb.h | 5 +- g10/keyedit.c | 8 +- g10/keyserver.c | 5 + g10/main.h | 2 + g10/misc.c | 47 ++++++++ g10/options.h | 17 ++- g10/packet.h | 1 - g10/parse-packet.c | 21 +--- g10/pkclist.c | 112 +++++++++--------- g10/revoke.c | 2 +- g10/sign.c | 43 ++++--- 20 files changed, 390 insertions(+), 271 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index bfac870c8..a04cb88d1 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,47 @@ +2003-05-02 David Shaw + + * packet.h, build-packet.c (build_sig_subpkt), export.c + (do_export_stream), import.c (remove_bad_stuff, import), + parse-packet.c (dump_sig_subpkt, parse_one_sig_subpkt): Remove + vestigal code for the old sig cache subpacket. This wasn't + completely harmless as it caused subpacket 101 to disappear on + import and export. + + * options.h, armor.c, cipher.c, g10.c, keyedit.c, pkclist.c, + sign.c, encode.c, getkey.c, revoke.c: The current flags for + different levels of PGP-ness are massively complex. This is step + one in simplifying them. No functional change yet, just use a + macro to check for compliance level. + + * sign.c (sign_file): Fix bug that causes spurious compression + preference warning. + + * sign.c (clearsign_file): Fix bug that prevents proper warning + message from appearing when clearsigning in --pgp2 mode with a + non-v3 RSA key. + + * main.h, misc.c (compliance_option_string, compliance_string, + compliance_failure), pkclist.c (build_pk_list), sign.c (sign_file, + clearsign_file), encode.c (encode_crypt, + write_pubkey_enc_from_list): New functions to put the "this + message may not be usable...." warning in one place. + + * options.h, g10.c (main): Part two of the simplification. Use a + single enum to indicate what we are compliant to (1991, 2440, + PGPx, etc.) + + * g10.c (main): Show errors for failure in export, send-keys, + recv-keys, and refresh-keys. + + * options.h, g10.c (main): Give algorithm warnings for algorithms + chosen against the --pgpX and --openpgp rules. + + * keydb.h, pkclist.c (algo_available): Make TIGER192 invalid in + --openpgp mode. + + * sign.c (sign_file), pkclist.c (algo_available): Allow passing a + hint of 0. + 2003-05-01 David Shaw * tdbio.c (create_version_record): Only create new trustdbs with diff --git a/g10/armor.c b/g10/armor.c index 8383345c2..98559d0c9 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -298,7 +298,7 @@ is_armor_header( byte *line, unsigned len ) /* Some mail programs on Windows seem to add spaces to the end of the line. This becomes strict if --openpgp is set. */ - if(!opt.rfc2440) + if(!RFC2440) while(*p==' ') p++; @@ -1334,5 +1334,3 @@ unarmor_pump (UnarmorPump x, int c) return rval; } - - diff --git a/g10/build-packet.c b/g10/build-packet.c index 3fec9a84c..8239e76b5 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -791,9 +791,6 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, nlen = 1; /* just a 1 byte length header */ switch( type ) { - case SIGSUBPKT_PRIV_VERIFY_CACHE: /*(obsolete)*/ - BUG(); - break; /* The issuer being unhashed is a historical oddity. It should work equally as well hashed. Of course, if even an unhashed issuer is tampered with, it makes it awfully hard diff --git a/g10/cipher.c b/g10/cipher.c index cb9f14916..ab7c9b676 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -55,7 +55,7 @@ write_header( cipher_filter_context_t *cfx, IOBUF a ) memset( &ed, 0, sizeof ed ); ed.len = cfx->datalen; ed.extralen = blocksize+2; - ed.new_ctb = !ed.len && !opt.rfc1991; + ed.new_ctb = !ed.len && !RFC1991; if( cfx->dek->use_mdc ) { ed.mdc_method = DIGEST_ALGO_SHA1; cfx->mdc_hash = md_open( DIGEST_ALGO_SHA1, 0 ); diff --git a/g10/encode.c b/g10/encode.c index a7396c98c..8a0766674 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -165,7 +165,7 @@ encode_simple( const char *filename, int mode, int compat ) compress_filter_context_t zfx; text_filter_context_t tfx; progress_filter_context_t pfx; - int do_compress = opt.compress && !opt.rfc1991; + int do_compress = opt.compress && !RFC1991; memset( &cfx, 0, sizeof cfx); memset( &afx, 0, sizeof afx); @@ -188,13 +188,13 @@ encode_simple( const char *filename, int mode, int compat ) /* Due the the fact that we use don't use an IV to encrypt the session key we can't use the new mode with RFC1991 because it has no S2K salt. RFC1991 always uses simple S2K. */ - if ( opt.rfc1991 && !compat ) + if ( RFC1991 && !compat ) compat = 1; cfx.dek = NULL; if( mode ) { s2k = m_alloc_clear( sizeof *s2k ); - s2k->mode = opt.rfc1991? 0:opt.s2k_mode; + s2k->mode = RFC1991? 0:opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; cfx.dek = passphrase_to_dek( NULL, 0, default_cipher_algo(), s2k, 2, @@ -247,7 +247,7 @@ encode_simple( const char *filename, int mode, int compat ) write_comment( out, opt.comment_string ); } #endif - if( s2k && !opt.rfc1991 ) { + if( s2k && !RFC1991 ) { PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; @@ -312,7 +312,7 @@ encode_simple( const char *filename, int mode, int compat ) pt->timestamp = make_timestamp(); pt->mode = opt.textmode? 't' : 'b'; pt->len = filesize; - pt->new_ctb = !pt->len && !opt.rfc1991; + pt->new_ctb = !pt->len && !RFC1991; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; @@ -391,7 +391,7 @@ encode_crypt( const char *filename, STRLIST remusr ) text_filter_context_t tfx; progress_filter_context_t pfx; PK_LIST pk_list,work_list; - int do_compress = opt.compress && !opt.rfc1991; + int do_compress = opt.compress && !RFC1991; memset( &cfx, 0, sizeof cfx); @@ -403,15 +403,14 @@ encode_crypt( const char *filename, STRLIST remusr ) if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) ) return rc; - if(opt.pgp2) { + if(PGP2) { for(work_list=pk_list; work_list; work_list=work_list->next) if(!(is_RSA(work_list->pk->pubkey_algo) && nbits_from_pk(work_list->pk)<=2048)) { log_info(_("you can only encrypt to RSA keys of 2048 bits or " "less in --pgp2 mode\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; + compliance_failure(); break; } } @@ -459,11 +458,10 @@ encode_crypt( const char *filename, STRLIST remusr ) if( cfx.dek->algo == -1 ) { cfx.dek->algo = CIPHER_ALGO_3DES; - if( opt.pgp2 ) { + if( PGP2 ) { log_info(_("unable to use the IDEA cipher for all of the keys " "you are encrypting to.\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; + compliance_failure(); } } } @@ -545,7 +543,7 @@ encode_crypt( const char *filename, STRLIST remusr ) pt->timestamp = make_timestamp(); pt->mode = opt.textmode ? 't' : 'b'; pt->len = filesize; - pt->new_ctb = !pt->len && !opt.rfc1991; + pt->new_ctb = !pt->len && !RFC1991; pt->buf = inp; pkt.pkttype = PKT_PLAINTEXT; pkt.pkt.plaintext = pt; @@ -715,16 +713,11 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out ) keyid_from_pk( pk, enc->keyid ); enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1)); - if(opt.throw_keyid && (opt.pgp2 || opt.pgp6 || opt.pgp7 || opt.pgp8)) + if(opt.throw_keyid && (PGP2 || PGP6 || PGP7 || PGP8)) { log_info(_("you may not use %s while in %s mode\n"), - "--throw-keyid", - opt.pgp2?"--pgp2":opt.pgp6?"--pgp6":opt.pgp7?"--pgp7":"--pgp8"); - - log_info(_("this message may not be usable by %s\n"), - opt.pgp2?"PGP 2.x":opt.pgp6?"PGP 6.x":opt.pgp7?"PGP 7.x":"PGP 8.x"); - - opt.pgp2=opt.pgp6=opt.pgp7=opt.pgp8=0; + "--throw-keyid",compliance_option_string()); + compliance_failure(); } /* Okay, what's going on: We have the session key somewhere in diff --git a/g10/export.c b/g10/export.c index 3a9a324d7..e036e2520 100644 --- a/g10/export.c +++ b/g10/export.c @@ -358,10 +358,6 @@ do_export_stream( IOBUF out, STRLIST users, int secret, if(ipkt->pkt.signature->numrevkeys) continue; } - - /* delete our verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed, - SIGSUBPKT_PRIV_VERIFY_CACHE); } /* Don't export attribs? */ diff --git a/g10/g10.c b/g10/g10.c index cf23bb81d..831ee50ed 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -1525,8 +1525,7 @@ main( int argc, char **argv ) #endif /* __riscos__ */ break; case oRFC1991: - opt.rfc1991 = 1; - opt.rfc2440 = 0; + opt.compliance = CO_RFC1991; opt.force_v4_certs = 0; opt.disable_mdc = 1; opt.escape_from = 1; @@ -1534,8 +1533,7 @@ main( int argc, char **argv ) case oOpenPGP: /* TODO: When 2440bis becomes a RFC, these may need changing. */ - opt.rfc1991 = 0; - opt.rfc2440 = 1; + opt.compliance = CO_RFC2440; opt.disable_mdc = 1; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; @@ -1552,19 +1550,17 @@ main( int argc, char **argv ) opt.s2k_mode = 3; /* iterated+salted */ opt.s2k_digest_algo = DIGEST_ALGO_SHA1; opt.s2k_cipher_algo = CIPHER_ALGO_3DES; - opt.pgp2 = 0; - opt.pgp6 = 0; - opt.pgp7 = 0; - opt.pgp8 = 0; break; - case oPGP2: opt.pgp2 = 1; break; - case oNoPGP2: opt.pgp2 = 0; break; - case oPGP6: opt.pgp6 = 1; break; - case oNoPGP6: opt.pgp6 = 0; break; - case oPGP7: opt.pgp7 = 1; break; - case oNoPGP7: opt.pgp7 = 0; break; - case oPGP8: opt.pgp8 = 1; break; - case oNoPGP8: opt.pgp8 = 0; break; + case oPGP2: opt.compliance = CO_PGP2; break; + case oPGP6: opt.compliance = CO_PGP6; break; + case oPGP7: opt.compliance = CO_PGP7; break; + case oPGP8: opt.compliance = CO_PGP8; break; + case oNoPGP2: + case oNoPGP6: + case oNoPGP7: + case oNoPGP8: + opt.compliance = CO_GNUPG; + break; case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; case oCompressSigs: opt.compress_sigs = 1; break; case oRunAsShmCP: @@ -1892,113 +1888,98 @@ main( int argc, char **argv ) set_debug(); /* Do these after the switch(), so they can override settings. */ - if(opt.pgp2 && (opt.pgp6 || opt.pgp7 || opt.pgp8)) - log_error(_("%s not allowed with %s!\n"), - "--pgp2",opt.pgp6?"--pgp6":opt.pgp7?"--pgp7":"--pgp8"); - else + if(PGP2) { - if(opt.pgp2) - { - int unusable=0; + int unusable=0; - if(cmd==aSign && !detached_sig) + if(cmd==aSign && !detached_sig) + { + log_info(_("you can only make detached or clear signatures " + "while in --pgp2 mode\n")); + unusable=1; + } + else if(cmd==aSignEncr || cmd==aSignSym) + { + log_info(_("you can't sign and encrypt at the " + "same time while in --pgp2 mode\n")); + unusable=1; + } + else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) + { + log_info(_("you must use files (and not a pipe) when " + "working with --pgp2 enabled.\n")); + unusable=1; + } + else if(cmd==aEncr || cmd==aSym) + { + /* Everything else should work without IDEA (except using + a secret key encrypted with IDEA and setting an IDEA + preference, but those have their own error + messages). */ + + if(check_cipher_algo(CIPHER_ALGO_IDEA)) { - log_info(_("you can only make detached or clear signatures " - "while in --pgp2 mode\n")); + log_info(_("encrypting a message in --pgp2 mode requires " + "the IDEA cipher\n")); + idea_cipher_warn(1); unusable=1; } - else if(cmd==aSignEncr || cmd==aSignSym) + else if(cmd==aSym) { - log_info(_("you can't sign and encrypt at the " - "same time while in --pgp2 mode\n")); - unusable=1; - } - else if(argc==0 && (cmd==aSign || cmd==aEncr || cmd==aSym)) - { - log_info(_("you must use files (and not a pipe) when " - "working with --pgp2 enabled.\n")); - unusable=1; - } - else if(cmd==aEncr || cmd==aSym) - { - /* Everything else should work without IDEA (except using - a secret key encrypted with IDEA and setting an IDEA - preference, but those have their own error - messages). */ - - if(check_cipher_algo(CIPHER_ALGO_IDEA)) - { - log_info(_("encrypting a message in --pgp2 mode requires " - "the IDEA cipher\n")); - idea_cipher_warn(1); - unusable=1; - } - else if(cmd==aSym) - { - /* This only sets IDEA for symmetric encryption - since it is set via select_algo_from_prefs for - pk encryption. */ - m_free(def_cipher_string); - def_cipher_string = m_strdup("idea"); - } - - /* PGP2 can't handle the output from the textmode - filter, so we disable it for anything that could - create a literal packet (only encryption and - symmetric encryption, since we disable signing - above). */ - if(!unusable) - opt.textmode=0; + /* This only sets IDEA for symmetric encryption + since it is set via select_algo_from_prefs for + pk encryption. */ + m_free(def_cipher_string); + def_cipher_string = m_strdup("idea"); } - if(unusable) - { - log_info(_("this message may not be usable by %s\n"), - "PGP 2.x"); - opt.pgp2=0; - } - else - { - opt.rfc1991 = 1; - opt.rfc2440 = 0; - opt.force_mdc = 0; - opt.disable_mdc = 1; - opt.force_v4_certs = 0; - opt.sk_comments = 0; - opt.escape_from = 1; - opt.force_v3_sigs = 1; - opt.pgp2_workarounds = 1; - opt.ask_sig_expire = 0; - opt.ask_cert_expire = 0; - m_free(def_digest_string); - def_digest_string = m_strdup("md5"); - opt.def_compress_algo = 1; - } + /* PGP2 can't handle the output from the textmode + filter, so we disable it for anything that could + create a literal packet (only encryption and + symmetric encryption, since we disable signing + above). */ + if(!unusable) + opt.textmode=0; } - else if(opt.pgp6) + + if(unusable) + compliance_failure(); + else { - opt.sk_comments=0; - opt.escape_from=1; - opt.force_v3_sigs=1; - opt.ask_sig_expire=0; - opt.def_compress_algo=1; - opt.force_mdc=0; - opt.disable_mdc=1; - } - else if(opt.pgp7) - { - opt.sk_comments=0; - opt.escape_from=1; - opt.force_v3_sigs=1; - opt.ask_sig_expire=0; - opt.def_compress_algo=1; - } - else if(opt.pgp8) - { - opt.escape_from=1; - opt.def_compress_algo=1; + opt.force_mdc = 0; + opt.disable_mdc = 1; + opt.force_v4_certs = 0; + opt.sk_comments = 0; + opt.escape_from = 1; + opt.force_v3_sigs = 1; + opt.pgp2_workarounds = 1; + opt.ask_sig_expire = 0; + opt.ask_cert_expire = 0; + m_free(def_digest_string); + def_digest_string = m_strdup("md5"); + opt.def_compress_algo = 1; } } + else if(PGP6) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + opt.force_mdc=0; + opt.disable_mdc=1; + } + else if(PGP7) + { + opt.sk_comments=0; + opt.escape_from=1; + opt.force_v3_sigs=1; + opt.ask_sig_expire=0; + } + else if(PGP8) + { + opt.escape_from=1; + } /* must do this after dropping setuid, because string_to... * may try to load an module */ @@ -2085,6 +2066,66 @@ main( int argc, char **argv ) if( log_get_errorcount(0) ) g10_exit(2); + /* Check our chosen algorithms against the list of legal + algorithms. */ + + if(!GNUPG) + { + const char *badalg=NULL; + preftype_t badtype=PREFTYPE_NONE; + + if(opt.def_cipher_algo + && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) + { + badalg=cipher_algo_to_string(opt.def_cipher_algo); + badtype=PREFTYPE_SYM; + } + else if(opt.def_digest_algo + && !algo_available(PREFTYPE_HASH,opt.def_digest_algo,NULL)) + { + badalg=digest_algo_to_string(opt.def_digest_algo); + badtype=PREFTYPE_HASH; + } + else if(opt.cert_digest_algo + && !algo_available(PREFTYPE_HASH,opt.cert_digest_algo,NULL)) + { + badalg=digest_algo_to_string(opt.cert_digest_algo); + badtype=PREFTYPE_HASH; + } + else if(opt.def_compress_algo!=-1 + && !algo_available(PREFTYPE_ZIP,opt.def_compress_algo,NULL)) + { + badalg=compress_algo_to_string(opt.def_compress_algo); + badtype=PREFTYPE_ZIP; + } + + if(badalg) + { + switch(badtype) + { + case PREFTYPE_SYM: + log_info(_("you may not use cipher algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_HASH: + log_info(_("you may not use digest algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + case PREFTYPE_ZIP: + log_info(_("you may not use compression algorithm \"%s\" " + "while in %s mode\n"), + badalg,compliance_option_string()); + break; + default: + BUG(); + } + + compliance_failure(); + } + } + /* set the random seed file */ if( use_random_seed ) { char *p = make_filename(opt.homedir, "random_seed", NULL ); @@ -2416,11 +2457,20 @@ main( int argc, char **argv ) for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); if( cmd == aSendKeys ) - keyserver_export( sl ); + rc=keyserver_export( sl ); else if( cmd == aRecvKeys ) - keyserver_import( sl ); + rc=keyserver_import( sl ); else - export_pubkeys( sl, opt.export_options ); + rc=export_pubkeys( sl, opt.export_options ); + if(rc) + { + if(cmd==aSendKeys) + log_error(_("keyserver send failed: %s\n"),g10_errstr(rc)); + else if(cmd==aRecvKeys) + log_error(_("keyserver receive failed: %s\n"),g10_errstr(rc)); + else + log_error(_("key export failed: %s\n"),g10_errstr(rc)); + } free_strlist(sl); break; @@ -2429,7 +2479,9 @@ main( int argc, char **argv ) for( ; argc; argc--, argv++ ) append_to_strlist2( &sl, *argv, utf8_strings ); - keyserver_search( sl ); + rc=keyserver_search( sl ); + if(rc) + log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); free_strlist(sl); break; @@ -2437,7 +2489,9 @@ main( int argc, char **argv ) sl = NULL; for( ; argc; argc--, argv++ ) add_to_strlist2( &sl, *argv, utf8_strings ); - keyserver_refresh(sl); + rc=keyserver_refresh(sl); + if(rc) + log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); free_strlist(sl); break; diff --git a/g10/getkey.c b/g10/getkey.c index a4403e523..86898141c 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -2074,7 +2074,7 @@ finish_lookup (GETKEY_CTX ctx) do not understand signatures made by a signing subkey. PGP 8 does. */ int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) || - ((opt.pgp6 || opt.pgp7) && (ctx->req_usage & PUBKEY_USAGE_SIG)); + ((PGP6 || PGP7) && (ctx->req_usage & PUBKEY_USAGE_SIG)); u32 latest_date; KBNODE latest_key; u32 curtime = make_timestamp (); diff --git a/g10/import.c b/g10/import.c index 4fb6f5690..cec24b8ad 100644 --- a/g10/import.c +++ b/g10/import.c @@ -60,7 +60,6 @@ static int import( IOBUF inp, const char* fname, struct stats_s *stats, unsigned int options ); static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); static void revocation_present(KBNODE keyblock); -static void remove_bad_stuff (KBNODE keyblock); static int import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, unsigned int options); static int import_secret_one( const char *fname, KBNODE keyblock, @@ -260,7 +259,6 @@ import( IOBUF inp, const char* fname, } while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { - remove_bad_stuff (keyblock); if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) rc = import_one( fname, keyblock, stats, options ); else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) @@ -450,22 +448,6 @@ read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ) return rc; } - -static void -remove_bad_stuff (KBNODE keyblock) -{ - KBNODE node; - - for (node=keyblock; node; node = node->next ) { - if( node->pkt->pkttype == PKT_SIGNATURE ) { - /* delete the subpackets we used to use for the - verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed, - SIGSUBPKT_PRIV_VERIFY_CACHE); - } - } -} - /* Walk through the subkeys on a pk to find if we have the PKS disease: multiple subkeys with their binding sigs stripped, and the sig for the first subkey placed after the last subkey. That is, diff --git a/g10/keydb.h b/g10/keydb.h index 8395c118f..7be5e7fff 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -172,8 +172,9 @@ void show_revocation_reason( PKT_public_key *pk, int mode ); int check_signatures_trust( PKT_signature *sig ); void release_pk_list( PK_LIST pk_list ); int build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ); -int select_algo_from_prefs( PK_LIST pk_list, int preftype, - int request, void *hint ); +int algo_available( preftype_t preftype, int algo, void *hint ); +int select_algo_from_prefs( PK_LIST pk_list, int preftype, + int request, void *hint ); int select_mdc_from_pklist (PK_LIST pk_list); /*-- skclist.c --*/ diff --git a/g10/keyedit.c b/g10/keyedit.c index 333552c38..2b96846ff 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -404,7 +404,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int all_v3=1; /* Are there any non-v3 sigs on this key already? */ - if(opt.pgp2) + if(PGP2) for(node=keyblock;node;node=node->next) if(node->pkt->pkttype==PKT_SIGNATURE && node->pkt->pkt.signature->version>3) @@ -690,7 +690,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, /* Is --pgp2 on, it's a v3 key, all the sigs on the key are currently v3 and we're about to sign it with a v4 sig? If so, danger! */ - if(opt.pgp2 && all_v3 && + if(PGP2 && all_v3 && (sk->version>3 || force_v4) && primary_pk->version<=3) { tty_printf(_("You may not make an OpenPGP signature on a " @@ -1349,11 +1349,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, break; case cmdADDPHOTO: - if (opt.rfc2440 || opt.rfc1991 || opt.pgp2) + if (RFC2440 || RFC1991 || PGP2) { tty_printf( _("This command is not allowed while in %s mode.\n"), - opt.rfc2440?"OpenPGP":opt.pgp2?"PGP2":"RFC-1991"); + RFC2440?"OpenPGP":PGP2?"PGP2":"RFC-1991"); break; } photo=1; diff --git a/g10/keyserver.c b/g10/keyserver.c index eb8169246..7759de198 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -206,6 +206,11 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno) ch++; } + + /* It would seem to be reasonable to limit the range of the + ports to values between 1-65535, but RFC 1738 and 1808 + imply there is no limit. Of course, the real world has + limits. */ } /* (any path part of the URI is discarded for now as no keyserver diff --git a/g10/main.h b/g10/main.h index 84a2705d8..a3a128b98 100644 --- a/g10/main.h +++ b/g10/main.h @@ -95,6 +95,8 @@ int string_to_compress_algo(const char *string); int check_compress_algo(int algo); int default_cipher_algo(void); int default_compress_algo(void); +void compliance_failure(void); +const char *compliance_option_string(void); /*-- helptext.c --*/ void display_online_help( const char *keyword ); diff --git a/g10/misc.c b/g10/misc.c index 08bbdc6fe..58d6bce5b 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -592,3 +592,50 @@ default_compress_algo(void) else return DEFAULT_COMPRESS_ALGO; } + +const char * +compliance_option_string(void) +{ + switch(opt.compliance) + { + case CO_RFC2440: + return "--openpgp"; + case CO_PGP2: + return "--pgp2"; + case CO_PGP6: + return "--pgp6"; + case CO_PGP7: + return "--pgp7"; + case CO_PGP8: + return "--pgp8"; + default: + return "???"; + } +} + +static const char * +compliance_string(void) +{ + switch(opt.compliance) + { + case CO_RFC2440: + return "OpenPGP"; + case CO_PGP2: + return "PGP 2.x"; + case CO_PGP6: + return "PGP 6.x"; + case CO_PGP7: + return "PGP 7.x"; + case CO_PGP8: + return "PGP 8.x"; + default: + return "???"; + } +} + +void +compliance_failure(void) +{ + log_info(_("this message may not be usable by %s\n"),compliance_string()); + opt.compliance=CO_GNUPG; +} diff --git a/g10/options.h b/g10/options.h index 69dc2119f..8b6c5a369 100644 --- a/g10/options.h +++ b/g10/options.h @@ -93,12 +93,10 @@ struct { we started storing the trust model inside the trustdb. */ enum {TM_CLASSIC=0, TM_PGP=1, TM_ALWAYS, TM_AUTO} trust_model; unsigned int force_ownertrust; - int pgp2; - int pgp6; - int pgp7; - int pgp8; - int rfc1991; - int rfc2440; + enum + { + CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 + } compliance; int pgp2_workarounds; unsigned int emulate_bugs; /* bug emulation flags EMUBUG_xxxx */ int shm_coprocess; @@ -211,5 +209,12 @@ struct { #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) #define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) +#define GNUPG (opt.compliance==CO_GNUPG) +#define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2) +#define RFC2440 (opt.compliance==CO_RFC2440) +#define PGP2 (opt.compliance==CO_PGP2) +#define PGP6 (opt.compliance==CO_PGP6) +#define PGP7 (opt.compliance==CO_PGP7) +#define PGP8 (opt.compliance==CO_PGP8) #endif /*G10_OPTIONS_H*/ diff --git a/g10/packet.h b/g10/packet.h index d357cfdb5..d8f25bb9c 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -354,7 +354,6 @@ typedef enum { SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ SIGSUBPKT_FEATURES =30, /* feature flags */ - SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result (obsolete)*/ SIGSUBPKT_FLAG_CRITICAL=128 } sigsubpkttype_t; diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 7b502067a..b9afb75ff 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -899,10 +899,12 @@ dump_sig_subpkt( int hashed, int type, int critical, for( i=0; i < length; i++ ) printf(" %02x", buffer[i] ); break; - case SIGSUBPKT_PRIV_VERIFY_CACHE: - p = "obsolete verification cache"; + default: + if(type>=100 && type<=110) + p="experimental / private subpacket"; + else + p = "?"; break; - default: p = "?"; break; } printf("%s)\n", p? p: ""); @@ -962,19 +964,6 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type ) if ( n != 2 ) break; return 0; - case SIGSUBPKT_PRIV_VERIFY_CACHE: - /* We used this in gpg 1.0.5 and 1.0.6 to cache signature - * verification results - it is no longer used. - * "GPG" 0x00 - * where mode == 1: valid data, stat == 0: invalid signature - * stat == 1: valid signature - * (because we use private data, we check our marker) */ - if( n < 6 ) - break; - if( buffer[0] != 'G' || buffer[1] != 'P' - || buffer[2] != 'G' || buffer[3] ) - return -2; - return 4; default: return -1; } return -3; diff --git a/g10/pkclist.c b/g10/pkclist.c index 85e792605..c12b3deb4 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -818,16 +818,13 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) { any_recipients = 1; - if((rov->flags&2) && (opt.pgp2 || opt.pgp6 || opt.pgp7)) + if((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8)) { log_info(_("you may not use %s while in %s mode\n"), "--hidden-recipient", - opt.pgp2?"--pgp2":opt.pgp6?"--pgp6":"--pgp7"); + compliance_option_string()); - log_info(_("this message may not be usable by %s\n"), - opt.pgp2?"PGP 2.x":opt.pgp6?"PGP 6.x":"PGP 7.x"); - - opt.pgp2=opt.pgp6=opt.pgp7=0; + compliance_failure(); } } else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { @@ -857,16 +854,13 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) r->flags = (rov->flags&2)?1:0; pk_list = r; - if(r->flags&1 && (opt.pgp2 || opt.pgp6 || opt.pgp7)) + if(r->flags&1 && (PGP2 || PGP6 || PGP7 || PGP8)) { log_info(_("you may not use %s while in %s mode\n"), "--hidden-encrypt-to", - opt.pgp2?"--pgp2":opt.pgp6?"--pgp6":"--pgp7"); + compliance_option_string()); - log_info(_("this message may not be usable by %s\n"), - opt.pgp2?"PGP 2.x":opt.pgp6?"PGP 6.x":"PGP 7.x"); - - opt.pgp2=opt.pgp6=opt.pgp7=0; + compliance_failure(); } } } @@ -1131,46 +1125,60 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use ) intersection"), and PGP has no mechanism to fix such a broken preference list, so I'm including it. -dms */ -static int -algo_available( int preftype, int algo, void *hint ) +int +algo_available( preftype_t preftype, int algo, void *hint ) { - if( preftype == PREFTYPE_SYM ) { - if( opt.pgp6 && ( algo != 1 && algo != 2 && algo != 3) ) - return 0; - - if( (opt.pgp7 || opt.pgp8) - && (algo != 1 && algo != 2 && algo != 3 - && algo != 7 && algo != 8 && algo != 9 && algo != 10) ) - return 0; - - return algo && !check_cipher_algo( algo ); - } - else if( preftype == PREFTYPE_HASH ) { - int bits=0; - - if(hint) - bits=*(int *)hint; - - if(bits && (bits != md_digest_length(algo))) - return 0; - - if( (opt.pgp6 || opt.pgp7) && (algo != 1 && algo != 2 && algo != 3) ) - return 0; - - if( opt.pgp8 && (algo != 1 && algo != 2 && algo != 3 && algo != 8)) - return 0; - - return algo && !check_digest_algo( algo ); - } - else if( preftype == PREFTYPE_ZIP ) { - if ( ( opt.pgp6 || opt.pgp7 || opt.pgp8 ) - && ( algo !=0 && algo != 1) ) - return 0; - - return !check_compress_algo( algo ); - } - else + if( preftype == PREFTYPE_SYM ) + { + if(PGP6 && (algo != CIPHER_ALGO_IDEA + && algo != CIPHER_ALGO_3DES + && algo != CIPHER_ALGO_CAST5)) return 0; + + if((PGP7 || PGP8) && (algo != CIPHER_ALGO_IDEA + && algo != CIPHER_ALGO_3DES + && algo != CIPHER_ALGO_CAST5 + && algo != CIPHER_ALGO_AES + && algo != CIPHER_ALGO_AES192 + && algo != CIPHER_ALGO_AES256 + && algo != CIPHER_ALGO_TWOFISH)) + return 0; + + return algo && !check_cipher_algo( algo ); + } + else if( preftype == PREFTYPE_HASH ) + { + if(hint && ((*(int *)hint) != md_digest_length(algo))) + return 0; + + if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5 + && algo != DIGEST_ALGO_SHA1 + && algo != DIGEST_ALGO_RMD160)) + return 0; + + + if(PGP8 && (algo != DIGEST_ALGO_MD5 + && algo != DIGEST_ALGO_SHA1 + && algo != DIGEST_ALGO_RMD160 + && algo != DIGEST_ALGO_SHA256)) + return 0; + + /* TIGER is not allowed any longer according to 2440bis. */ + if( RFC2440 && algo == DIGEST_ALGO_TIGER ) + return 0; + + return algo && !check_digest_algo( algo ); + } + else if( preftype == PREFTYPE_ZIP ) + { + if((PGP6 || PGP7 || PGP8) && (algo != COMPRESS_ALGO_NONE + && algo != COMPRESS_ALGO_ZIP)) + return 0; + + return !check_compress_algo( algo ); + } + else + return 0; } @@ -1197,7 +1205,7 @@ select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) memset( mask, 0, 8 * sizeof *mask ); if( preftype == PREFTYPE_SYM ) { - if( opt.pgp2 && + if( PGP2 && pkr->pk->version < 4 && pkr->pk->selfsigversion < 4 ) mask[0] |= (1<<1); /* IDEA is implicitly there for v3 keys @@ -1215,7 +1223,7 @@ select_algo_from_prefs(PK_LIST pk_list, int preftype, int request, void *hint) wasn't locked at MD5, we don't support sign+encrypt in --pgp2 mode, and that's the only time PREFTYPE_HASH is used anyway. -dms */ - if( opt.pgp2 && + if( PGP2 && pkr->pk->version < 4 && pkr->pk->selfsigversion < 4 ) mask[0] |= (1<<1); /* MD5 is there for v3 keys with v3 diff --git a/g10/revoke.c b/g10/revoke.c index 5e66090c4..302924163 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -521,7 +521,7 @@ gen_revoke( const char *uname ) goto leave; } - if(opt.pgp2 || opt.pgp6 || opt.pgp7 | opt.pgp8) + if(PGP2 || PGP6 || PGP7 || PGP8) { /* Use a minimal pk for PGPx mode, since PGP can't import bare revocation certificates. */ diff --git a/g10/sign.c b/g10/sign.c index 8311bdb08..852632098 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -338,7 +338,7 @@ hash_for(int pubkey_algo, int packet_version ) return opt.def_digest_algo; else if( recipient_digest_algo ) return recipient_digest_algo; - else if(opt.pgp2 && pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 ) + else if(PGP2 && pubkey_algo == PUBKEY_ALGO_RSA && packet_version < 4 ) { /* Old-style PGP only understands MD5 */ return DIGEST_ALGO_MD5; @@ -510,7 +510,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode) pt->timestamp = make_timestamp (); pt->mode = ptmode; pt->len = filesize; - pt->new_ctb = !pt->len && !opt.rfc1991; + pt->new_ctb = !pt->len && !RFC1991; pt->buf = inp; init_packet(&pkt); pkt.pkttype = PKT_PLAINTEXT; @@ -561,7 +561,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, MD_HANDLE hash, /* build the signature packet */ sig = m_alloc_clear (sizeof *sig); - if(opt.force_v3_sigs || opt.rfc1991) + if(opt.force_v3_sigs || RFC1991) sig->version=3; else if(duration || opt.sig_policy_url || opt.sig_notation_data) sig->version=4; @@ -660,18 +660,17 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( fname && filenames->next && (!detached || encryptflag) ) log_bug("multiple files can only be detached signed"); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) duration=ask_expire_interval(1); if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) goto leave; - if(opt.pgp2 && !only_old_style(sk_list)) + if(PGP2 && !only_old_style(sk_list)) { log_info(_("you can only detach-sign with PGP 2.x style keys " "while in --pgp2 mode\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; + compliance_failure(); } if(encryptflag && (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC ))) @@ -744,7 +743,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, hashlen=20; if((algo= - select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1,&hashlen))>0) + select_algo_from_prefs(pk_list,PREFTYPE_HASH,-1, + hashlen?&hashlen:NULL))>0) recipient_digest_algo=algo; } } @@ -757,7 +757,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, if( !multifile ) iobuf_push_filter( inp, md_filter, &mfx ); - if( detached && !encryptflag && !opt.rfc1991 ) + if( detached && !encryptflag && !RFC1991 ) afx.what = 2; if( opt.armor && !outfile ) @@ -787,9 +787,9 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, select_algo_from_prefs(pk_list,PREFTYPE_ZIP,-1,NULL))==-1) compr_algo=default_compress_algo(); } - else if(!opt.expert && - select_algo_from_prefs(pk_list,PREFTYPE_ZIP, - compr_algo,NULL)!=compr_algo) + else if(!opt.expert && pk_list + && select_algo_from_prefs(pk_list,PREFTYPE_ZIP, + compr_algo,NULL)!=compr_algo) log_info(_("forcing compression algorithm %s (%d) " "violates recipient preferences\n"), compress_algo_to_string(compr_algo),compr_algo); @@ -803,7 +803,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } /* Write the one-pass signature packets if needed */ - if (!detached && !opt.rfc1991) { + if (!detached && !RFC1991) { rc = write_onepass_sig_packets (sk_list, out, opt.textmode && !outfile ? 0x01:0x00); if (rc) @@ -897,14 +897,14 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) int rc = 0; SK_LIST sk_list = NULL; SK_LIST sk_rover = NULL; - int old_style = opt.rfc1991; + int old_style = RFC1991; int only_md5 = 0; u32 duration=0; memset( &afx, 0, sizeof afx); init_packet( &pkt ); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) duration=ask_expire_interval(1); if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) ) @@ -913,12 +913,11 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) if( !old_style && !duration ) old_style = only_old_style( sk_list ); - if(!old_style && opt.pgp2) + if(PGP2 && !only_old_style(sk_list)) { log_info(_("you can only clearsign with PGP 2.x style keys " "while in --pgp2 mode\n")); - log_info(_("this message may not be usable by %s\n"),"PGP 2.x"); - opt.pgp2=0; + compliance_failure(); } /* prepare iobufs */ @@ -1045,7 +1044,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) memset( &cfx, 0, sizeof cfx); init_packet( &pkt ); - if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !opt.rfc1991) + if(opt.ask_sig_expire && !opt.force_v3_sigs && !opt.batch && !RFC1991) duration=ask_expire_interval(1); rc = build_sk_list (locusr, &sk_list, 1, PUBKEY_USAGE_SIG); @@ -1064,7 +1063,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* prepare key */ s2k = m_alloc_clear( sizeof *s2k ); - s2k->mode = opt.rfc1991? 0:opt.s2k_mode; + s2k->mode = RFC1991? 0:opt.s2k_mode; s2k->hash_algo = opt.s2k_digest_algo; algo = default_cipher_algo(); @@ -1102,7 +1101,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* Write the symmetric key packet */ /*(current filters: armor)*/ - if (!opt.rfc1991) { + if (!RFC1991) { PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc ); enc->version = 4; enc->cipher_algo = cfx.dek->algo; @@ -1126,7 +1125,7 @@ sign_symencrypt_file (const char *fname, STRLIST locusr) /* Write the one-pass signature packets */ /*(current filters: zip - encrypt - armor)*/ - if (!opt.rfc1991) { + if (!RFC1991) { rc = write_onepass_sig_packets (sk_list, out, opt.textmode? 0x01:0x00); if (rc)