diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 55 | ||||
-rw-r--r-- | g10/armor.c | 47 | ||||
-rw-r--r-- | g10/encode.c | 18 | ||||
-rw-r--r-- | g10/gpg.c | 36 | ||||
-rw-r--r-- | g10/import.c | 150 | ||||
-rw-r--r-- | g10/keyedit.c | 2 | ||||
-rw-r--r-- | g10/misc.c | 69 | ||||
-rw-r--r-- | g10/options.h | 9 | ||||
-rw-r--r-- | g10/sign.c | 58 |
9 files changed, 271 insertions, 173 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index 3fedb9979..e4702b041 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,58 @@ +2007-10-25 David Shaw <[email protected]> (wk) + + From 1.4 (October): + + * gpg.c (main): Add --require-cross-certification to + --openpgp/--rfc4880 mode. + + * gpg.c (main): Disable --rfc2440-text and --force-v3-sigs by + default. Enable --require-cross-certification by default. + --openpgp (--rfc4880) is the same as --rfc2440 except with + "--enable-dsa2 --no-rfc2440-text --escape-from-lines". + + * misc.c (compliance_option_string, compliance_failure): Minor + cleanup. + + * armor.c (is_armor_header): Comment about 4880. + + * options.h, gpg.c (main): Add --rfc4880, and make --openpgp an + alias to it. --rfc2440 now stands alone. For now, use the old + 2440 defaults for 4880. + * misc.c (compliance_option_string): Ditto. + + * keyedit.c (keyedit_menu): Use compliance_option_string() instead + of printing the compliance modes here. + +2007-10-25 David Shaw <[email protected]> (wk) + + From 1.4 (September): + + * import.c (collapse_uids): Significant speedup for de-duping user + IDs. + +2007-10-25 David Shaw <[email protected]> (wk) + + From 1.4 (July): + + * armor.c (parse_header_line): Improve test so that the header + test only allows "Hash" in the signed data section. + + * armor.c (is_armor_tag): New. Detect if an armor header matches + 2440bis-21. + (parse_header_line): Call it here, as bis-21 requires warning the + user (but continuing to process the message) when seeing an + unknown header. + + * encode.c (encode_crypt): Missed one call to + setup_plaintext_name(). This is bug#809. + + * sign.c (mk_notation_policy_etc): Expect all sigs that this is + called for are >=v4. + (write_signature_packets, make_keysig_packet): Only call it for + >=v4 sigs. This allows --force-v3-sigs and --force-v4-certs to + enable or disable notations, policies, and keyserver URLs. This + is bug#800. + 2007-10-19 Werner Koch <[email protected]> * passphrase.c (passphrase_get): Use new utf8 switching fucntions. diff --git a/g10/armor.c b/g10/armor.c index 1a9f82e89..76a2bdfbd 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -1,6 +1,6 @@ /* armor.c - Armor flter - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -308,7 +308,19 @@ parse_hash_header( const char *line ) return found; } +/* Returns true if this is a valid armor tag as per RFC-2440bis-21. */ +static int +is_armor_tag(const char *line) +{ + if(strncmp(line,"Version",7)==0 + || strncmp(line,"Comment",7)==0 + || strncmp(line,"MessageID",9)==0 + || strncmp(line,"Hash",4)==0 + || strncmp(line,"Charset",7)==0) + return 1; + return 0; +} /**************** * Check whether this is a armor line. @@ -338,7 +350,8 @@ is_armor_header( byte *line, unsigned len ) --rfc2440 is set since 2440 reads "The header lines, therefore, MUST start at the beginning of a line, and MUST NOT have text following them on the same line." It is unclear whether "text" - refers to all text or just non-whitespace text. */ + refers to all text or just non-whitespace text. 4880 clarified + this was only non-whitespace text. */ if(RFC2440) { @@ -418,16 +431,32 @@ parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len ) putc('\n', stderr); } - if( afx->in_cleartext ) { + if( afx->in_cleartext ) + { if( (hashes=parse_hash_header( line )) ) - afx->hashes |= hashes; + afx->hashes |= hashes; else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) ) - afx->not_dash_escaped = 1; - else { + afx->not_dash_escaped = 1; + else + { log_error(_("invalid clearsig header\n")); return -1; - } - } + } + } + else if(!is_armor_tag(line)) + { + /* Section 6.2: "Unknown keys should be reported to the user, + but OpenPGP should continue to process the message." Note + that in a clearsigned message this applies to the signature + part (i.e. "BEGIN PGP SIGNATURE") and not the signed data + ("BEGIN PGP SIGNED MESSAGE"). The only key allowed in the + signed data section is "Hash". */ + + log_info(_("unknown armor header: ")); + print_string( stderr, line, len, 0 ); + putc('\n', stderr); + } + return 1; } diff --git a/g10/encode.c b/g10/encode.c index 196d213d2..4a5733220 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -598,22 +598,8 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey ) if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out))) goto leave; - if (!opt.no_literal) { - /* setup the inner packet */ - if( filename || opt.set_filename ) { - char *s = make_basename( opt.set_filename ? opt.set_filename - : filename, - iobuf_get_real_fname( inp ) ); - pt = xmalloc( sizeof *pt + strlen(s) - 1 ); - pt->namelen = strlen(s); - memcpy(pt->name, s, pt->namelen ); - xfree(s); - } - else { /* no filename */ - pt = xmalloc( sizeof *pt - 1 ); - pt->namelen = 0; - } - } + if (!opt.no_literal) + pt=setup_plaintext_name(filename,inp); if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) { @@ -1,6 +1,6 @@ /* gpg.c - The GnuPG utility (main for gpg) * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * 2006, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -194,6 +194,7 @@ enum cmd_and_opt_values oGnuPG, oRFC1991, oRFC2440, + oRFC4880, oOpenPGP, oPGP2, oPGP6, @@ -520,6 +521,7 @@ static ARGPARSE_OPTS opts[] = { { oGnuPG, "no-pgp8", 0, "@"}, { oRFC1991, "rfc1991", 0, "@"}, { oRFC2440, "rfc2440", 0, "@" }, + { oRFC4880, "rfc4880", 0, "@" }, { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, { oPGP6, "pgp6", 0, "@"}, @@ -1902,8 +1904,8 @@ main (int argc, char **argv ) opt.marginals_needed = 3; opt.max_cert_depth = 5; opt.pgp2_workarounds = 1; - opt.force_v3_sigs = 1; opt.escape_from = 1; + opt.flags.require_cross_cert = 1; opt.import_options=IMPORT_SK2PK; opt.export_options=EXPORT_ATTRIBUTES; opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; @@ -1917,7 +1919,6 @@ main (int argc, char **argv ) opt.min_cert_level=2; set_screen_dimensions(); opt.keyid_format=KF_SHORT; - opt.rfc2440_text=1; opt.def_sig_expire="0"; opt.def_cert_expire="0"; set_homedir ( default_homedir () ); @@ -2303,11 +2304,34 @@ main (int argc, char **argv ) opt.escape_from = 1; break; case oOpenPGP: + case oRFC4880: + /* This is effectively the same as RFC2440, but with + "--enable-dsa2 --no-rfc2440-text --escape-from-lines + --require-cross-certification". */ + opt.compliance = CO_RFC4880; + opt.flags.dsa2 = 1; + opt.flags.require_cross_cert = 1; + opt.rfc2440_text = 0; + opt.allow_non_selfsigned_uid = 1; + opt.allow_freeform_uid = 1; + opt.pgp2_workarounds = 0; + opt.escape_from = 1; + opt.force_v3_sigs = 0; + opt.compress_keys = 0; /* not mandated, but we do it */ + opt.compress_sigs = 0; /* ditto. */ + opt.not_dash_escaped = 0; + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; + break; case oRFC2440: - /* TODO: When 2440bis becomes a RFC, set new values for - oOpenPGP. */ - opt.rfc2440_text=1; opt.compliance = CO_RFC2440; + opt.flags.dsa2 = 0; + opt.rfc2440_text = 1; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; diff --git a/g10/import.c b/g10/import.c index a3d0fecb8..fbfb18d0e 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1,6 +1,6 @@ /* import.c - import a key into our key storage. - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1649,90 +1649,102 @@ delete_inv_parts( const char *fname, KBNODE keyblock, * It may happen that the imported keyblock has duplicated user IDs. * We check this here and collapse those user IDs together with their * sigs into one. - * Returns: True if the keyblock hash changed. + * Returns: True if the keyblock has changed. */ int collapse_uids( KBNODE *keyblock ) { - KBNODE n, n2; - int in_uid; - int any=0; + KBNODE uid1; + int any=0; + + for(uid1=*keyblock;uid1;uid1=uid1->next) + { + KBNODE uid2; - restart: - for( n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype != PKT_USER_ID ) + if(uid1->pkt->pkttype!=PKT_USER_ID) + continue; + + for(uid2=uid1->next;uid2;uid2=uid2->next) + { + if(uid2->pkt->pkttype!=PKT_USER_ID) continue; - for( n2 = n->next; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - && !cmp_user_ids( n->pkt->pkt.user_id, - n2->pkt->pkt.user_id ) ) { - /* found a duplicate */ - any = 1; - if( !n2->next - || n2->next->pkt->pkttype == PKT_USER_ID - || n2->next->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->next->pkt->pkttype == PKT_SECRET_SUBKEY ) { - /* no more signatures: delete the user ID - * and start over */ - remove_kbnode( keyblock, n2 ); - } - else { - /* The simple approach: Move one signature and - * then start over to delete the next one :-( */ - move_kbnode( keyblock, n2->next, n->next ); + + if(cmp_user_ids(uid1->pkt->pkt.user_id, + uid2->pkt->pkt.user_id)==0) + { + /* We have a duplicated uid */ + KBNODE sig1,last; + + any=1; + + /* Now take uid2's signatures, and attach them to + uid1 */ + for(last=uid2;last->next;last=last->next) + { + if(last->next->pkt->pkttype==PKT_USER_ID + || last->next->pkt->pkttype==PKT_PUBLIC_SUBKEY + || last->next->pkt->pkttype==PKT_SECRET_SUBKEY) + break; } - goto restart; - } - } - } - if( !any ) - return 0; - restart_sig: - /* now we may have duplicate signatures on one user ID: fix this */ - for( in_uid = 0, n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype == PKT_USER_ID ) - in_uid = 1; - else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n->pkt->pkttype == PKT_SECRET_SUBKEY ) - in_uid = 0; - else if( in_uid ) { - n2 = n; - do { - KBNODE ncmp = NULL; - for( ; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->pkt->pkttype == PKT_SECRET_SUBKEY ) + /* Snip out uid2 */ + (find_prev_kbnode(*keyblock,uid2,0))->next=last->next; + + /* Now put uid2 in place as part of uid1 */ + last->next=uid1->next; + uid1->next=uid2; + remove_kbnode(keyblock,uid2); + + /* Now dedupe uid1 */ + for(sig1=uid1->next;sig1;sig1=sig1->next) + { + KBNODE sig2; + + if(sig1->pkt->pkttype==PKT_USER_ID + || sig1->pkt->pkttype==PKT_PUBLIC_SUBKEY + || sig1->pkt->pkttype==PKT_SECRET_SUBKEY) + break; + + if(sig1->pkt->pkttype!=PKT_SIGNATURE) + continue; + + for(sig2=sig1->next,last=sig1;sig2;last=sig2,sig2=sig2->next) + { + if(sig2->pkt->pkttype==PKT_USER_ID + || sig2->pkt->pkttype==PKT_PUBLIC_SUBKEY + || sig2->pkt->pkttype==PKT_SECRET_SUBKEY) break; - if( n2->pkt->pkttype != PKT_SIGNATURE ) - ; - else if( !ncmp ) - ncmp = n2; - else if( !cmp_signatures( ncmp->pkt->pkt.signature, - n2->pkt->pkt.signature )) { - remove_kbnode( keyblock, n2 ); - goto restart_sig; + + if(sig2->pkt->pkttype!=PKT_SIGNATURE) + continue; + + if(cmp_signatures(sig1->pkt->pkt.signature, + sig2->pkt->pkt.signature)==0) + { + /* We have a match, so delete the second + signature */ + remove_kbnode(&uid1,sig2); + sig2=last; + } } } - n2 = ncmp? ncmp->next : NULL; - } while( n2 ); + } } } - if(!opt.quiet) - { - const char *key="???"; + if(any && !opt.quiet) + { + const char *key="???"; - if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) - key=keystr_from_pk(n->pkt->pkt.public_key); - else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) - key=keystr_from_sk(n->pkt->pkt.secret_key); + if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) + key=keystr_from_pk(uid1->pkt->pkt.public_key); + else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) + key=keystr_from_sk(uid1->pkt->pkt.secret_key); - log_info(_("key %s: duplicated user ID detected - merged\n"),key); - } + log_info(_("key %s: duplicated user ID detected - merged\n"),key); + } - return 1; + return any; } /* Check for a 0x20 revocation from a revocation key that is not diff --git a/g10/keyedit.c b/g10/keyedit.c index 77f401798..1078758dd 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1803,7 +1803,7 @@ keyedit_menu( const char *username, strlist_t locusr, { tty_printf( _("This command is not allowed while in %s mode.\n"), - RFC2440?"OpenPGP":PGP2?"PGP2":"RFC-1991"); + compliance_option_string()); break; } photo=1; diff --git a/g10/misc.c b/g10/misc.c index 3781b2c27..96bb6c559 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -831,47 +831,64 @@ default_compress_algo(void) const char * compliance_option_string(void) { + char *ver="???"; + 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 "???"; + case CO_GNUPG: return "--gnupg"; + case CO_RFC4880: return "--openpgp"; + case CO_RFC2440: return "--rfc2440"; + case CO_RFC1991: return "--rfc1991"; + case CO_PGP2: return "--pgp2"; + case CO_PGP6: return "--pgp6"; + case CO_PGP7: return "--pgp7"; + case CO_PGP8: return "--pgp8"; } + + return ver; } -static const char * -compliance_string(void) +void +compliance_failure(void) { + char *ver="???"; + switch(opt.compliance) { + case CO_GNUPG: + ver="GnuPG"; + break; + + case CO_RFC4880: + ver="OpenPGP"; + break; + case CO_RFC2440: - return "OpenPGP"; + ver="OpenPGP (older)"; + break; + + case CO_RFC1991: + ver="old PGP"; + break; + case CO_PGP2: - return "PGP 2.x"; + ver="PGP 2.x"; + break; + case CO_PGP6: - return "PGP 6.x"; + ver="PGP 6.x"; + break; + case CO_PGP7: - return "PGP 7.x"; + ver="PGP 7.x"; + break; + case CO_PGP8: - return "PGP 8.x"; - default: - return "???"; + ver="PGP 8.x"; + break; } -} -void -compliance_failure(void) -{ - log_info(_("this message may not be usable by %s\n"),compliance_string()); + log_info(_("this message may not be usable by %s\n"),ver); opt.compliance=CO_GNUPG; } diff --git a/g10/options.h b/g10/options.h index 5918d089e..be7394e35 100644 --- a/g10/options.h +++ b/g10/options.h @@ -1,6 +1,6 @@ /* options.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -103,7 +103,8 @@ struct int force_ownertrust; enum { - CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 + CO_GNUPG, CO_RFC4880, CO_RFC2440, CO_RFC1991, CO_PGP2, + CO_PGP6, CO_PGP7, CO_PGP8 } compliance; enum { @@ -290,10 +291,12 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; #define GNUPG (opt.compliance==CO_GNUPG) #define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2) #define RFC2440 (opt.compliance==CO_RFC2440) +#define RFC4880 (opt.compliance==CO_RFC4880) #define PGP2 (opt.compliance==CO_PGP2) #define PGP6 (opt.compliance==CO_PGP6) #define PGP7 (opt.compliance==CO_PGP7) #define PGP8 (opt.compliance==CO_PGP8) +#define PGPX (PGP2 || PGP6 || PGP7 || PGP8) /* Various option flags. Note that there should be no common string names between the IMPORT_ and EXPORT_ flags as they can be mixed in diff --git a/g10/sign.c b/g10/sign.c index 33830d0ce..6e3671dbd 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -1,6 +1,6 @@ /* sign.c - sign data - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -66,32 +66,17 @@ mk_notation_policy_etc( PKT_signature *sig, struct notation *nd=NULL; struct expando_args args; + assert(sig->version>=4); + memset(&args,0,sizeof(args)); args.pk=pk; args.sk=sk; - /* It is actually impossible to get here when making a v3 key - signature since keyedit.c:sign_uids will automatically bump a - signature with a notation or policy url up to v4, but it is - good to do these checks anyway. */ - /* notation data */ if(IS_SIG(sig) && opt.sig_notations) - { - if(sig->version<4) - log_error(_("can't put notation data into v3 (PGP 2.x style) " - "signatures\n")); - else - nd=opt.sig_notations; - } + nd=opt.sig_notations; else if( IS_CERT(sig) && opt.cert_notations ) - { - if(sig->version<4) - log_error(_("can't put notation data into v3 (PGP 2.x style) " - "key signatures\n")); - else - nd=opt.cert_notations; - } + nd=opt.cert_notations; if(nd) { @@ -116,21 +101,9 @@ mk_notation_policy_etc( PKT_signature *sig, /* set policy URL */ if( IS_SIG(sig) && opt.sig_policy_url ) - { - if(sig->version<4) - log_error(_("can't put a policy URL into v3 (PGP 2.x style) " - "signatures\n")); - else - pu=opt.sig_policy_url; - } + pu=opt.sig_policy_url; else if( IS_CERT(sig) && opt.cert_policy_url ) - { - if(sig->version<4) - log_error(_("can't put a policy URL into v3 key (PGP 2.x style) " - "signatures\n")); - else - pu=opt.cert_policy_url; - } + pu=opt.cert_policy_url; for(;pu;pu=pu->next) { @@ -153,12 +126,7 @@ mk_notation_policy_etc( PKT_signature *sig, /* preferred keyserver URL */ if( IS_SIG(sig) && opt.sig_keyserver_url ) - { - if(sig->version<4) - log_info("can't put a preferred keyserver URL into v3 signatures\n"); - else - pu=opt.sig_keyserver_url; - } + pu=opt.sig_keyserver_url; for(;pu;pu=pu->next) { @@ -689,8 +657,10 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash, BUG (); if (sig->version >= 4) + { build_sig_subpkt_from_sig (sig); - mk_notation_policy_etc (sig, NULL, sk); + mk_notation_policy_etc (sig, NULL, sk); + } hash_sigversion_to_magic (md, sig); gcry_md_final (md); @@ -1487,8 +1457,10 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, sig->expiredate=sig->timestamp+duration; sig->sig_class = sigclass; if( sig->version >= 4 ) + { build_sig_subpkt_from_sig( sig ); - mk_notation_policy_etc( sig, pk, sk ); + mk_notation_policy_etc( sig, pk, sk ); + } /* Crucial that the call to mksubpkt comes LAST before the calls to finalize the sig as that makes it possible for the mksubpkt |