diff --git a/g10/ChangeLog b/g10/ChangeLog index 57dd35c4b..92135de49 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,52 @@ +2003-05-21 David Shaw + + * trustdb.h, trustdb.c (is_disabled), gpgv.c (is_disabled): Rename + is_disabled to cache_disabled_value, which now takes a pk and not + just the keyid. This is for speed since there is no need to + re-fetch a key when we already have that key handy. Cache the + result of the check so we don't need to hit the trustdb more than + once. + + * getkey.c (skip_disabled): New function to get a pk and call + is_disabled on it. (key_byname): Use it here. + + * packet.h, getkey.c (skip_disabled), keylist.c + (print_capabilities): New "pk_is_disabled" macro to retrieve the + cached disabled value if available, and fill it in via + cache_disabled_value if not available. + + * trustdb.c (get_validity): Cache the disabled value since we have + it handy and it might be useful later. + + * parse-packet.c (parse_key): Clear disabled flag when parsing a + new key. Just in case someone forgets to clear the whole key. + + * getkey.c (merge_selfsigs_main): Add an "if all else fails" path + for setting a single user ID primary when there are multiple set + primaries all at the same second, or no primaries set and the most + recent user IDs are at the same second, or no signed user IDs at + all. This is arbitrary, but deterministic. + + * exec.h, photoid.h: Add copyright message. + + * keylist.c (list_keyblock_print): Don't dump attribs for + revoked/expired/etc uids for non-colon key listings. This is for + consistency with --show-photos. + + * main.h, keylist.c (dump_attribs), mainproc.c + (check_sig_and_print): Dump attribs if --attrib-fd is set when + verifying signatures. + + * g10.c (main): New --gnupg option to disable the various + --openpgp, --pgpX, etc. options. This is the same as --no-XXXX + for those options. + + * revoke.c (ask_revocation_reason): Clear old reason if user + elects to repeat question. This is bug 153. + + * keyedit.c (sign_uids): Show keyid of the key making the + signature. + 2003-05-21 Werner Koch * progress.c (handle_progress) diff --git a/g10/exec.h b/g10/exec.h index 427f25810..25369dc34 100644 --- a/g10/exec.h +++ b/g10/exec.h @@ -1,3 +1,23 @@ +/* exec.h + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + #ifndef _EXEC_H_ #define _EXEC_H_ diff --git a/g10/g10.c b/g10/g10.c index 831ee50ed..b7b36c27a 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -169,16 +169,13 @@ enum cmd_and_opt_values { aNull = 0, oMarginalsNeeded, oMaxCertDepth, oLoadExtension, + oGnuPG, oRFC1991, oOpenPGP, oPGP2, - oNoPGP2, oPGP6, - oNoPGP6, oPGP7, - oNoPGP7, oPGP8, - oNoPGP8, oCipherAlgo, oDigestAlgo, oCertDigestAlgo, @@ -458,16 +455,17 @@ static ARGPARSE_OPTS opts[] = { { oMaxCertDepth, "max-cert-depth", 1, "@" }, { oTrustedKey, "trusted-key", 2, N_("|KEYID|ultimately trust this key")}, { oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")}, + { oGnuPG, "gnupg", 0, "@"}, + { oGnuPG, "no-pgp2", 0, "@"}, + { oGnuPG, "no-pgp6", 0, "@"}, + { oGnuPG, "no-pgp7", 0, "@"}, + { oGnuPG, "no-pgp8", 0, "@"}, { oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")}, { oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")}, { oPGP2, "pgp2", 0, N_("set all packet, cipher and digest options to PGP 2.x behavior")}, - { oNoPGP2, "no-pgp2", 0, "@"}, { oPGP6, "pgp6", 0, "@"}, - { oNoPGP6, "no-pgp6", 0, "@"}, { oPGP7, "pgp7", 0, "@"}, - { oNoPGP7, "no-pgp7", 0, "@"}, { oPGP8, "pgp8", 0, "@"}, - { oNoPGP8, "no-pgp8", 0, "@"}, { oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")}, { oS2KDigest, "s2k-digest-algo",2, N_("|NAME|use message digest algorithm NAME for passphrases")}, @@ -1551,16 +1549,11 @@ main( int argc, char **argv ) opt.s2k_digest_algo = DIGEST_ALGO_SHA1; opt.s2k_cipher_algo = CIPHER_ALGO_3DES; 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 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 oGnuPG: opt.compliance = CO_GNUPG; break; case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break; case oCompressSigs: opt.compress_sigs = 1; break; case oRunAsShmCP: diff --git a/g10/getkey.c b/g10/getkey.c index 86898141c..44e571ce4 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1,5 +1,6 @@ /* getkey.c - Get a key from the database - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -724,6 +725,27 @@ classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) } +static int +skip_disabled(void *dummy,u32 *keyid) +{ + int rc,disabled=0; + PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + + rc = get_pubkey(pk, keyid); + if(rc) + { + log_error("error checking disabled status of %08lX: %s\n", + (ulong)keyid[1],g10_errstr(rc)); + goto leave; + } + + disabled=pk_is_disabled(pk); + + leave: + free_public_key(pk); + return disabled; +} + /**************** * Try to get the pubkey by the userid. This function looks for the * first pubkey certificate which has the given name in a user_id. @@ -774,7 +796,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist, && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR16 && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR20 && ctx->items[n].mode!=KEYDB_SEARCH_MODE_FPR) - ctx->items[n].skipfnc=is_disabled; + ctx->items[n].skipfnc=skip_disabled; } ctx->kr_handle = keydb_new (secmode); @@ -1296,12 +1318,12 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n); if (p && n && (p[0] & 0x01)) uid->mdc_feature = 1; + /* and the keyserver modify flag */ uid->ks_modify = 1; p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KS_FLAGS, &n); if (p && n && (p[0] & 0x80)) uid->ks_modify = 0; - } static void @@ -1670,14 +1692,38 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) if ( k->pkt->pkttype == PKT_USER_ID && !k->pkt->pkt.user_id->attrib_data) { PKT_user_id *uid = k->pkt->pkt.user_id; - if ( uid->is_primary && uid->created > uiddate ) { - uiddate = uid->created; - uidnode = k; - } - if ( !uid->is_primary && uid->created > uiddate2 ) { - uiddate2 = uid->created; - uidnode2 = k; - } + if (uid->is_primary) + { + if(uid->created > uiddate) + { + uiddate = uid->created; + uidnode = k; + } + else if(uid->created==uiddate && uidnode) + { + /* The dates are equal, so we need to do a + different (and arbitrary) comparison. This + should rarely, if ever, happen. It's good to + try and guarantee that two different GnuPG + users with two different keyrings at least pick + the same primary. */ + if(cmp_user_ids(uid,uidnode->pkt->pkt.user_id)>0) + uidnode=k; + } + } + else + { + if(uid->created > uiddate2) + { + uiddate2 = uid->created; + uidnode2 = k; + } + else if(uid->created==uiddate2 && uidnode2) + { + if(cmp_user_ids(uid,uidnode2->pkt->pkt.user_id)>0) + uidnode2=k; + } + } } } if ( uidnode ) { @@ -1692,23 +1738,43 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) } } else if( uidnode2 ) { - /* none is flagged primary - use the latest user ID we have */ + /* none is flagged primary - use the latest user ID we have, + and disambiguate with the arbitrary packet comparison. */ uidnode2->pkt->pkt.user_id->is_primary = 1; } else { - /* None of our uids were self-signed, so pick the first one to - be the primary. This is the best we can do here since - there are no self sigs to date the uids. */ + /* None of our uids were self-signed, so pick the one that + sorts first to be the primary. This is the best we can do + here since there are no self sigs to date the uids. */ + + uidnode = NULL; for(k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next ) { - if(k->pkt->pkttype==PKT_USER_ID && - !k->pkt->pkt.user_id->attrib_data) + if(k->pkt->pkttype==PKT_USER_ID + && !k->pkt->pkt.user_id->attrib_data) { - k->pkt->pkt.user_id->is_primary=1; - break; + if(!uidnode) + { + uidnode=k; + uidnode->pkt->pkt.user_id->is_primary=1; + continue; + } + else + { + if(cmp_user_ids(k->pkt->pkt.user_id, + uidnode->pkt->pkt.user_id)>0) + { + uidnode->pkt->pkt.user_id->is_primary=0; + uidnode=k; + uidnode->pkt->pkt.user_id->is_primary=1; + } + else + k->pkt->pkt.user_id->is_primary=0; /* just to be + safe */ + } } } } diff --git a/g10/gpgv.c b/g10/gpgv.c index caa669171..b4aa31b96 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -234,7 +234,7 @@ check_signatures_trust( PKT_signature *sig ) */ int -is_disabled(void *dummy,u32 *keyid) +cache_disabled_value(PKT_public_key *pk) { return 0; } diff --git a/g10/keyedit.c b/g10/keyedit.c index 2b96846ff..017e53e0c 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -765,7 +765,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, p = get_user_id( sk_keyid, &n ); tty_print_utf8_string( p, n ); m_free(p); p = NULL; - tty_printf("\"\n"); + tty_printf("\" (%08lX)\n",(ulong)sk_keyid[1]); if(selfsig) { diff --git a/g10/keylist.c b/g10/keylist.c index 0eb321d71..f2c387b02 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -358,23 +358,17 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) } } - if ( keyblock ) { /* figure our the usable capabilities */ + if ( keyblock ) { /* figure out the usable capabilities */ KBNODE k; int enc=0, sign=0, cert=0, disabled=0; for (k=keyblock; k; k = k->next ) { if ( k->pkt->pkttype == PKT_PUBLIC_KEY || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { - u32 kid[2]; pk = k->pkt->pkt.public_key; - if(k->pkt->pkttype==PKT_PUBLIC_KEY) - { - keyid_from_pk(pk,kid); - - if(is_disabled(NULL,kid)) - disabled=1; - } + if(pk->is_primary) + disabled=pk_is_disabled(pk); if ( pk->is_valid && !pk->is_revoked && !pk->has_expired ) { if ( pk->pubkey_usage & PUBKEY_USAGE_ENC ) @@ -416,13 +410,13 @@ print_capabilities (PKT_public_key *pk, PKT_secret_key *sk, KBNODE keyblock) putchar(':'); } -static void dump_attribs(const PKT_user_id *uid, - PKT_public_key *pk,PKT_secret_key *sk) +void +dump_attribs(const PKT_user_id *uid,PKT_public_key *pk,PKT_secret_key *sk) { int i; if(!attrib_fp) - BUG(); + return; for(i=0;inumattribs;i++) { @@ -498,8 +492,6 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) { if( node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode ) { - if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) - dump_attribs(node->pkt->pkt.user_id,pk,sk); /* don't list revoked or expired UIDS unless we are in * verbose mode and signature listing has not been * requested */ @@ -508,6 +500,9 @@ list_keyblock_print ( KBNODE keyblock, int secret, int fpr, void *opaque ) node->pkt->pkt.user_id->is_expired )) continue; + if(attrib_fp && node->pkt->pkt.user_id->attrib_data!=NULL) + dump_attribs(node->pkt->pkt.user_id,pk,sk); + if( any ) printf("uid%*s", 29, ""); diff --git a/g10/main.h b/g10/main.h index a3a128b98..67d2f9853 100644 --- a/g10/main.h +++ b/g10/main.h @@ -212,6 +212,8 @@ void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode); void show_policy_url(PKT_signature *sig,int indent); void show_notation(PKT_signature *sig,int indent); +void dump_attribs(const PKT_user_id *uid, + PKT_public_key *pk,PKT_secret_key *sk); void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); void print_pubkey_info (PKT_public_key *pk); diff --git a/g10/mainproc.c b/g10/mainproc.c index d2acdeadf..fbc2394eb 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1313,8 +1313,6 @@ check_sig_and_print( CTX c, KBNODE node ) } } } - - tstr = asctimestamp(sig->timestamp); astr = pubkey_algo_to_string( sig->pubkey_algo ); @@ -1431,9 +1429,14 @@ check_sig_and_print( CTX c, KBNODE node ) !un->pkt->pkt.user_id->attrib_data ) continue; - if(opt.show_photos && un->pkt->pkt.user_id->attrib_data) - show_photos(un->pkt->pkt.user_id->attribs, - un->pkt->pkt.user_id->numattribs,pk,NULL); + if(un->pkt->pkt.user_id->attrib_data) + { + dump_attribs(un->pkt->pkt.user_id,pk,NULL); + + if(opt.show_photos) + show_photos(un->pkt->pkt.user_id->attribs, + un->pkt->pkt.user_id->numattribs,pk,NULL); + } log_info( _(" aka \"")); print_utf8_string( log_stream(), un->pkt->pkt.user_id->name, @@ -1692,7 +1695,3 @@ proc_tree( CTX c, KBNODE node ) dump_kbnode (node); } } - - - - diff --git a/g10/packet.h b/g10/packet.h index d8f25bb9c..290afac68 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -211,6 +211,7 @@ typedef struct { u32 main_keyid[2]; /* keyid of the primary key */ u32 keyid[2]; /* calculated by keyid_from_pk() */ byte is_primary; + byte is_disabled; /* 0 for unset, 1 for enabled, 2 for disabled. */ prefitem_t *prefs; /* list of preferences (may be NULL) */ int mdc_feature; /* mdc feature set */ PKT_user_id *user_id; /* if != NULL: found by that uid */ @@ -223,6 +224,10 @@ typedef struct { MPI pkey[PUBKEY_MAX_NPKEY]; } PKT_public_key; +/* Evaluates as true if the pk is disabled, and false if it isn't. If + there is no disable value cached, fill one in. */ +#define pk_is_disabled(a) (((a)->is_disabled)?((a)->is_disabled==2):(cache_disabled_value((a)))) + typedef struct { u32 timestamp; /* key made */ u32 expiredate; /* expires at this date or 0 if not at all */ diff --git a/g10/parse-packet.c b/g10/parse-packet.c index b9afb75ff..2ce4748a6 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1,5 +1,6 @@ /* parse-packet.c - read packets - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, + * 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1546,6 +1547,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen, pk->req_usage = 0; pk->pubkey_usage = 0; /* not yet used */ pk->is_revoked = 0; + pk->is_disabled = 0; pk->keyid[0] = 0; pk->keyid[1] = 0; } diff --git a/g10/photoid.h b/g10/photoid.h index 45d104f8c..187ca5ba2 100644 --- a/g10/photoid.h +++ b/g10/photoid.h @@ -1,3 +1,23 @@ +/* photoid.h + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + /* Photo ID functions */ #ifndef _PHOTOID_H_ diff --git a/g10/revoke.c b/g10/revoke.c index 302924163..a45d2d623 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -580,6 +580,7 @@ ask_revocation_reason( int key_rev, int cert_rev, int hint ) const char *code_text = NULL; do { + code=-1; m_free(description); description = NULL; diff --git a/g10/trustdb.c b/g10/trustdb.c index 55519ed9f..457d83b9d 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -950,23 +950,17 @@ clear_validity (PKT_public_key *pk) /* Return true if key is disabled */ int -is_disabled(void *dummy,u32 *keyid) +cache_disabled_value(PKT_public_key *pk) { int rc; TRUSTREC trec; - int disabled=0; /* default to not disabled */ - PKT_public_key *pk=m_alloc_clear(sizeof(PKT_public_key)); + int disabled=0; - init_trustdb (); + if(pk->is_disabled) + return (pk->is_disabled==2); + + init_trustdb(); - rc = get_pubkey(pk, keyid); - if(rc) - { - log_error("error checking disabled status of %08lX: %s\n", - (ulong)keyid[1],g10_errstr(rc)); - goto leave; - } - rc = read_trust_record (pk, &trec); if (rc && rc != -1) { @@ -979,9 +973,15 @@ is_disabled(void *dummy,u32 *keyid) if(trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) disabled=1; + /* Cache it for later so we don't need to look at the trustdb every + time */ + if(disabled) + pk->is_disabled=2; + else + pk->is_disabled=1; + leave: - free_public_key(pk); - return disabled; + return disabled; } /* @@ -1085,7 +1085,12 @@ get_validity (PKT_public_key *pk, PKT_user_id *uid) } if ( (trec.r.trust.ownertrust & TRUST_FLAG_DISABLED) ) - validity |= TRUST_FLAG_DISABLED; + { + validity |= TRUST_FLAG_DISABLED; + pk->is_disabled=2; + } + else + pk->is_disabled=1; leave: /* set some flags direct from the key */ diff --git a/g10/trustdb.h b/g10/trustdb.h index 8545eab1b..720385a06 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -52,7 +52,7 @@ int string_to_trust_value (const char *str); void revalidation_mark (void); int trustdb_pending_check(void); -int is_disabled(void *dummy,u32 *keyid); +int cache_disabled_value(PKT_public_key *pk); unsigned int get_validity (PKT_public_key *pk, PKT_user_id *uid); int get_validity_info (PKT_public_key *pk, PKT_user_id *uid);