diff --git a/g10/ChangeLog b/g10/ChangeLog index c683455be..c3a6ecfac 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,18 @@ +2003-08-30 David Shaw + + * main.h, keygen.c (keygen_add_keyserver_url): Signature callback + for adding a keyserver URL. + + * keyedit.c (keyedit_menu, menu_set_keyserver_url): New command to + set preferred keyserver to specified (or all) user IDs. + + * build-packet.c (build_sig_subpkt): Set preferred keyserver flag + while building a preferred keyserver subpacket. + + * keylist.c (show_policy_url): Policy URLs might be UTF8. + + * keyedit.c (menu_addrevoker): Fix leaking a few bytes. + 2003-08-29 David Shaw * keyedit.c (show_key_with_all_names): Use list-option diff --git a/g10/build-packet.c b/g10/build-packet.c index 86aa07dc2..af97be423 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -747,6 +747,10 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, sig->flags.policy_url=1; break; + case SIGSUBPKT_PREF_KS: + sig->flags.pref_ks=1; + break; + case SIGSUBPKT_EXPORTABLE: if(buffer[0]) sig->flags.exportable=1; diff --git a/g10/keyedit.c b/g10/keyedit.c index 5b6f4f9df..db1589a43 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -55,6 +55,7 @@ static int menu_addrevoker( KBNODE pub_keyblock, static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock ); +static int menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ); static int menu_select_uid( KBNODE keyblock, int idx ); static int menu_select_key( KBNODE keyblock, int idx ); static int count_uids( KBNODE keyblock ); @@ -173,6 +174,9 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node, if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATION)) show_notation(sig,3,0); + + if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER)) + show_keyserver_url(sig,3,0); } return (sigrc == '!'); @@ -1106,7 +1110,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, - cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP }; + cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, + cmdNOP }; static struct { const char *name; enum cmdids id; int need_sk; @@ -1151,6 +1156,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, { N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences (verbose)") }, { N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") }, { N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") }, + { N_("keyserver"),cmdPREFKS , 1,1,0, N_("set preferred keyserver")}, { N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") }, { N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") }, { N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") }, @@ -1604,6 +1610,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands, } break; + case cmdPREFKS: + if( menu_set_keyserver_url ( keyblock, sec_keyblock ) ) { + merge_keys_and_selfsig( keyblock ); + modified = 1; + redisplay = 1; + } + break; + case cmdNOP: break; @@ -2654,16 +2668,22 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive ) answer=cpr_get_utf8("keyedit.add_revoker", _("Enter the user ID of the designated revoker: ")); if(answer[0]=='\0' || answer[0]=='\004') - goto fail; + { + m_free(answer); + goto fail; + } rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); if(rc) { log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc)); + m_free(answer); continue; } + m_free(answer); + fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen); if(fprlen!=20) { @@ -3140,6 +3160,100 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock ) } +static int +menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock ) +{ + PKT_secret_key *sk; /* copy of the main sk */ + PKT_public_key *main_pk; + PKT_user_id *uid; + KBNODE node; + u32 keyid[2]; + int selected, select_all; + int modified = 0; + char *answer; + + no_primary_warning(pub_keyblock,1); + + answer=cpr_get_utf8("keyedit.add_keyserver", + _("Enter your preferred keyserver URL: ")); + if(answer[0]=='\0' || answer[0]=='\004') + { + m_free(answer); + return 0; + } + + select_all = !count_selected_uids (pub_keyblock); + + node = find_kbnode( sec_keyblock, PKT_SECRET_KEY ); + sk = copy_secret_key( NULL, node->pkt->pkt.secret_key); + + /* Now we can actually change the self signature(s) */ + main_pk = NULL; + uid = NULL; + selected = 0; + for ( node=pub_keyblock; node; node = node->next ) { + if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) + break; /* ready */ + + if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk( main_pk, keyid ); + } + else if ( node->pkt->pkttype == PKT_USER_ID ) { + uid = node->pkt->pkt.user_id; + selected = select_all || (node->flag & NODFLG_SELUID); + } + else if ( main_pk && uid && selected + && node->pkt->pkttype == PKT_SIGNATURE ) { + PKT_signature *sig = node->pkt->pkt.signature; + if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && (uid && (sig->sig_class&~3) == 0x10) ) { + if( sig->version < 4 ) { + char *user=utf8_to_native(uid->name,strlen(uid->name),0); + + log_info(_("skipping v3 self-signature on user id \"%s\"\n"), + user); + m_free(user); + } + else { + /* This is a selfsignature which is to be replaced + * We have to ignore v3 signatures because they are + * not able to carry the preferences */ + PKT_signature *newsig; + PACKET *newpkt; + int rc; + + rc = update_keysig_packet (&newsig, sig, + main_pk, uid, NULL, + sk, + keygen_add_keyserver_url, + answer ); + if( rc ) { + log_error ("update_keysig_packet failed: %s\n", + g10_errstr(rc)); + m_free(answer); + free_secret_key( sk ); + return 0; + } + /* replace the packet */ + newpkt = m_alloc_clear( sizeof *newpkt ); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet( node->pkt ); + m_free( node->pkt ); + node->pkt = newpkt; + modified = 1; + } + } + } + } + + m_free(answer); + free_secret_key( sk ); + return modified; +} + + /**************** * Select one user id or remove all selection if index is 0. * Returns: True if the selection changed; diff --git a/g10/keygen.c b/g10/keygen.c index edf9badce..4b736e16d 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -580,6 +580,16 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque ) return 0; } +int +keygen_add_keyserver_url(PKT_signature *sig, void *opaque) +{ + const char *url=opaque; + + build_sig_subpkt(sig,SIGSUBPKT_PREF_KS,url,strlen(url)); + + return 0; +} + int keygen_add_revkey(PKT_signature *sig, void *opaque) { diff --git a/g10/keylist.c b/g10/keylist.c index dace1e742..c5f6bb785 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -174,7 +174,6 @@ show_policy_url(PKT_signature *sig,int indent,int mode) for(i=0;i