aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyedit.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/keyedit.c3281
1 files changed, 0 insertions, 3281 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c
deleted file mode 100644
index 71d2858b7..000000000
--- a/g10/keyedit.c
+++ /dev/null
@@ -1,3281 +0,0 @@
-/* keyedit.c - keyedit stuff
- * Copyright (C) 1998, 1999, 2000, 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
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-
-#include "options.h"
-#include "packet.h"
-#include "errors.h"
-#include "iobuf.h"
-#include "keydb.h"
-#include "memory.h"
-#include "photoid.h"
-#include "util.h"
-#include "main.h"
-#include "trustdb.h"
-#include "filter.h"
-#include "ttyio.h"
-#include "status.h"
-#include "i18n.h"
-
-static void show_prefs( PKT_user_id *uid, int verbose );
-static void show_key_with_all_names( KBNODE keyblock, int only_marked,
- int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
-static void show_key_and_fingerprint( KBNODE keyblock );
-static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
-static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
-static int menu_delsig( KBNODE pub_keyblock );
-static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
-static int menu_addrevoker( KBNODE pub_keyblock,
- KBNODE sec_keyblock, int sensitive );
-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_select_uid( KBNODE keyblock, int idx );
-static int menu_select_key( KBNODE keyblock, int idx );
-static int count_uids( KBNODE keyblock );
-static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
-static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
-static int count_selected_uids( KBNODE keyblock );
-static int real_uids_left( KBNODE keyblock );
-static int count_selected_keys( KBNODE keyblock );
-static int menu_revsig( KBNODE keyblock );
-static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
-static int enable_disable_key( KBNODE keyblock, int disable );
-static void menu_showphoto( KBNODE keyblock );
-
-static int update_trust=0;
-
-#define CONTROL_D ('D' - 'A' + 1)
-
-#define NODFLG_BADSIG (1<<0) /* bad signature */
-#define NODFLG_NOKEY (1<<1) /* no public key */
-#define NODFLG_SIGERR (1<<2) /* other sig error */
-
-#define NODFLG_MARK_A (1<<4) /* temporary mark */
-#define NODFLG_DELSIG (1<<5) /* to be deleted */
-
-#define NODFLG_SELUID (1<<8) /* indicate the selected userid */
-#define NODFLG_SELKEY (1<<9) /* indicate the selected key */
-#define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
-
-struct sign_attrib {
- int non_exportable,non_revocable;
- struct revocation_reason_info *reason;
-};
-
-/****************
- * Print information about a signature, check it and return true
- * if the signature is okay. NODE must be a signature packet.
- */
-static int
-print_and_check_one_sig( KBNODE keyblock, KBNODE node,
- int *inv_sigs, int *no_key, int *oth_err,
- int *is_selfsig, int print_without_key )
-{
- PKT_signature *sig = node->pkt->pkt.signature;
- int rc, sigrc;
- int is_rev = sig->sig_class == 0x30;
-
- /* TODO: Make sure a cached sig record here still has the pk that
- issued it. See also keylist.c:list_keyblock_print */
-
- switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) {
- case 0:
- node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
- sigrc = '!';
- break;
- case G10ERR_BAD_SIGN:
- node->flag = NODFLG_BADSIG;
- sigrc = '-';
- if( inv_sigs )
- ++*inv_sigs;
- break;
- case G10ERR_NO_PUBKEY:
- case G10ERR_UNU_PUBKEY:
- node->flag = NODFLG_NOKEY;
- sigrc = '?';
- if( no_key )
- ++*no_key;
- break;
- default:
- node->flag = NODFLG_SIGERR;
- sigrc = '%';
- if( oth_err )
- ++*oth_err;
- break;
- }
- if( sigrc != '?' || print_without_key ) {
- tty_printf("%s%c%c %c%c%c%c%c %08lX %s ",
- is_rev? "rev":"sig",sigrc,
- (sig->sig_class-0x10>0 &&
- sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
- sig->flags.exportable?' ':'L',
- sig->flags.revocable?' ':'R',
- sig->flags.policy_url?'P':' ',
- sig->flags.notation?'N':' ',
- sig->flags.expired?'X':' ',
- (ulong)sig->keyid[1], datestr_from_sig(sig));
- if( sigrc == '%' )
- tty_printf("[%s] ", g10_errstr(rc) );
- else if( sigrc == '?' )
- ;
- else if( *is_selfsig ) {
- tty_printf( is_rev? _("[revocation]")
- : _("[self-signature]") );
- }
- else {
- size_t n;
- char *p = get_user_id( sig->keyid, &n );
- tty_print_utf8_string2( p, n, 40 );
- m_free(p);
- }
- tty_printf("\n");
-
- if(sig->flags.policy_url && opt.show_policy_url)
- show_policy_url(sig,3);
-
- if(sig->flags.notation && opt.show_notation)
- show_notation(sig,3);
- }
-
- return (sigrc == '!');
-}
-
-
-
-/****************
- * Check the keysigs and set the flags to indicate errors.
- * Returns true if error found.
- */
-static int
-check_all_keysigs( KBNODE keyblock, int only_selected )
-{
- KBNODE kbctx;
- KBNODE node;
- int inv_sigs = 0;
- int no_key = 0;
- int oth_err = 0;
- int has_selfsig = 0;
- int mis_selfsig = 0;
- int selected = !only_selected;
- int anyuid = 0;
-
- for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- PKT_user_id *uid = node->pkt->pkt.user_id;
-
- if( only_selected )
- selected = (node->flag & NODFLG_SELUID);
- if( selected ) {
- tty_printf("uid ");
- tty_print_utf8_string( uid->name, uid->len );
- tty_printf("\n");
- if( anyuid && !has_selfsig )
- mis_selfsig++;
- has_selfsig = 0;
- anyuid = 1;
- }
- }
- else if( selected && node->pkt->pkttype == PKT_SIGNATURE
- && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
- || node->pkt->pkt.signature->sig_class == 0x30 ) ) {
- int selfsig;
-
- if( print_and_check_one_sig( keyblock, node, &inv_sigs,
- &no_key, &oth_err, &selfsig, 0 ) ) {
- if( selfsig )
- has_selfsig = 1;
- }
- /* Hmmm: should we update the trustdb here? */
- }
- }
- if( !has_selfsig )
- mis_selfsig++;
- if( inv_sigs == 1 )
- tty_printf(_("1 bad signature\n") );
- else if( inv_sigs )
- tty_printf(_("%d bad signatures\n"), inv_sigs );
- if( no_key == 1 )
- tty_printf(_("1 signature not checked due to a missing key\n") );
- else if( no_key )
- tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
- if( oth_err == 1 )
- tty_printf(_("1 signature not checked due to an error\n") );
- else if( oth_err )
- tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
- if( mis_selfsig == 1 )
- tty_printf(_("1 user ID without valid self-signature detected\n"));
- else if( mis_selfsig )
- tty_printf(_("%d user IDs without valid self-signatures detected\n"),
- mis_selfsig);
-
- return inv_sigs || no_key || oth_err || mis_selfsig;
-}
-
-
-
-
-static int
-sign_mk_attrib( PKT_signature *sig, void *opaque )
-{
- struct sign_attrib *attrib = opaque;
- byte buf[8];
-
- if( attrib->non_exportable ) {
- buf[0] = 0; /* not exportable */
- build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
- }
-
- if( attrib->non_revocable ) {
- buf[0] = 0; /* not revocable */
- build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 );
- }
-
- if( attrib->reason )
- revocation_reason_build_cb( sig, attrib->reason );
-
- return 0;
-}
-
-
-
-/****************
- * Loop over all locusr and and sign the uids after asking.
- * If no user id is marked, all user ids will be signed;
- * if some user_ids are marked those will be signed.
- */
-static int
-sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
- int local , int nonrevocable )
-{
- int rc = 0;
- SK_LIST sk_list = NULL;
- SK_LIST sk_rover = NULL;
- PKT_secret_key *sk = NULL;
- KBNODE node, uidnode;
- PKT_public_key *primary_pk=NULL;
- int select_all = !count_selected_uids(keyblock);
- int all_v3=1;
-
- /* Are there any non-v3 sigs on this key already? */
- if(opt.pgp2)
- for(node=keyblock;node;node=node->next)
- if(node->pkt->pkttype==PKT_SIGNATURE &&
- node->pkt->pkt.signature->version>3)
- {
- all_v3=0;
- break;
- }
-
- /* build a list of all signators.
- *
- * We use the CERT flag to request the primary which must always
- * be one which is capable of signing keys. I can't see a reason
- * why to sign keys using a subkey. Implementation of USAGE_CERT
- * is just a hack in getkey.c and does not mean that a subkey
- * marked as certification capable will be used */
- rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT);
- if( rc )
- goto leave;
-
- /* loop over all signators */
- for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
- u32 sk_keyid[2],pk_keyid[2];
- size_t n;
- char *p;
- int force_v4=0,class=0,selfsig=0;
- u32 duration=0,timestamp=0;
-
- if(local || nonrevocable ||
- opt.cert_policy_url || opt.cert_notation_data)
- force_v4=1;
-
- /* we have to use a copy of the sk, because make_keysig_packet
- * may remove the protection from sk and if we did other
- * changes to the secret key, we would save the unprotected
- * version */
- if( sk )
- free_secret_key(sk);
- sk = copy_secret_key( NULL, sk_rover->sk );
- keyid_from_sk( sk, sk_keyid );
- /* set mark A for all selected user ids */
- for( node=keyblock; node; node = node->next ) {
- if( select_all || (node->flag & NODFLG_SELUID) )
- node->flag |= NODFLG_MARK_A;
- else
- node->flag &= ~NODFLG_MARK_A;
- }
- /* reset mark for uids which are already signed */
- uidnode = NULL;
- for( node=keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- primary_pk=node->pkt->pkt.public_key;
- keyid_from_pk( primary_pk, pk_keyid );
-
- /* Is this a self-sig? */
- if(pk_keyid[0]==sk_keyid[0] && pk_keyid[1]==sk_keyid[1])
- {
- selfsig=1;
- /* Do not force a v4 sig here, otherwise it would
- be difficult to remake a v3 selfsig. If this
- is a v3->v4 promotion case, then we set
- force_v4 later anyway. */
- force_v4=0;
- }
- }
- else if( node->pkt->pkttype == PKT_USER_ID ) {
- uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
- if(uidnode)
- {
- char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
- uidnode->pkt->pkt.user_id->len,
- 0);
-
- if(uidnode->pkt->pkt.user_id->is_revoked)
- {
- tty_printf(_("User ID \"%s\" is revoked."),user);
-
- if(opt.expert)
- {
- tty_printf("\n");
- /* No, so remove the mark and continue */
- if(!cpr_get_answer_is_yes("sign_uid.revoke_okay",
- _("Are you sure you "
- "still want to sign "
- "it? (y/N) ")))
- uidnode->flag &= ~NODFLG_MARK_A;
- }
- else
- {
- uidnode->flag &= ~NODFLG_MARK_A;
- tty_printf(_(" Unable to sign.\n"));
- }
- }
- else if(!uidnode->pkt->pkt.user_id->created)
- {
- tty_printf(_("WARNING: user ID \"%s\" is not "
- "self-signed.\n"),user);
- }
-
- m_free(user);
- }
- }
- else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
- && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
- if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
- && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
- char buf[50];
- char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
- uidnode->pkt->pkt.user_id->len,
- 0);
-
- /* It's a v3 self-sig. Make it into a v4 self-sig? */
- if(node->pkt->pkt.signature->version<4 && selfsig)
- {
- tty_printf(_("The self-signature on \"%s\"\n"
- "is a PGP 2.x-style signature.\n"),user);
-
- /* Note that the regular PGP2 warning below
- still applies if there are no v4 sigs on
- this key at all. */
-
- if(opt.expert)
- if(cpr_get_answer_is_yes("sign_uid.v4_promote_okay",
- _("Do you want to promote "
- "it to an OpenPGP self-"
- "signature? (y/N) ")))
- {
- force_v4=1;
- node->flag|=NODFLG_DELSIG;
- continue;
- }
- }
-
- if(!node->pkt->pkt.signature->flags.exportable && !local)
- {
- /* It's a local sig, and we want to make a
- exportable sig. */
- tty_printf(_("Your current signature on \"%s\"\n"
- "is a local signature.\n"),user);
-
- if(cpr_get_answer_is_yes("sign_uid.local_promote_okay",
- _("Do you want to promote "
- "it to a full exportable "
- "signature? (y/N) ")))
- {
- /* Mark these for later deletion. We
- don't want to delete them here, just in
- case the replacement signature doesn't
- happen for some reason. We only delete
- these after the replacement is already
- in place. */
-
- node->flag|=NODFLG_DELSIG;
- continue;
- }
- }
-
- /* Fixme: see whether there is a revocation in which
- * case we should allow to sign it again. */
- if (!node->pkt->pkt.signature->flags.exportable && local)
- tty_printf(_(
- "\"%s\" was already locally signed by key %08lX\n"),
- user,(ulong)sk_keyid[1] );
- else
- tty_printf(_(
- "\"%s\" was already signed by key %08lX\n"),
- user,(ulong)sk_keyid[1] );
- sprintf (buf, "%08lX%08lX",
- (ulong)sk->keyid[0], (ulong)sk->keyid[1] );
- write_status_text (STATUS_ALREADY_SIGNED, buf);
- uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
-
- m_free(user);
- }
- }
- }
- /* check whether any uids are left for signing */
- if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
- tty_printf(_("Nothing to sign with key %08lX\n"),
- (ulong)sk_keyid[1] );
- continue;
- }
- /* Ask whether we really should sign these user id(s) */
- tty_printf("\n");
- show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 );
- tty_printf("\n");
-
- if(primary_pk->expiredate && !selfsig)
- {
- u32 now=make_timestamp();
-
- if(primary_pk->expiredate<=now)
- {
- tty_printf(_("This key has expired!"));
-
- if(opt.expert)
- {
- tty_printf(" ");
- if(!cpr_get_answer_is_yes("sign_uid.expired_okay",
- _("Are you sure you still "
- "want to sign it? (y/N) ")))
- continue;
- }
- else
- {
- tty_printf(_(" Unable to sign.\n"));
- continue;
- }
- }
- else
- {
- char *answer;
-
- tty_printf(_("This key is due to expire on %s.\n"),
- expirestr_from_pk(primary_pk));
-
- answer=cpr_get("sign_uid.expire",
- _("Do you want your signature to "
- "expire at the same time? (Y/n) "));
- if(answer_is_yes_no_default(answer,1))
- {
- /* This fixes the signature timestamp we're going
- to make as now. This is so the expiration date
- is exactly correct, and not a few seconds off
- (due to the time it takes to answer the
- questions, enter the passphrase, etc). */
- timestamp=now;
- duration=primary_pk->expiredate-now;
- force_v4=1;
- }
-
- cpr_kill_prompt();
- m_free(answer);
- }
- }
-
- /* Only ask for duration if we haven't already set it to match
- the expiration of the pk */
- if(opt.ask_cert_expire && !duration && !selfsig)
- duration=ask_expire_interval(1);
-
- if(duration)
- force_v4=1;
-
- /* 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 &&
- (sk->version>3 || force_v4) && primary_pk->version<=3)
- {
- tty_printf(_("You may not make an OpenPGP signature on a "
- "PGP 2.x key while in --pgp2 mode.\n"));
- tty_printf(_("This would make the key unusable in PGP 2.x.\n"));
-
- if(opt.expert)
- {
- if(!cpr_get_answer_is_yes("sign_uid.v4_on_v3_okay",
- _("Are you sure you still "
- "want to sign it? (y/N) ")))
- continue;
-
- all_v3=0;
- }
- else
- continue;
- }
-
- if(selfsig)
- ;
- else if(opt.batch)
- class=0x10+opt.def_cert_check_level;
- else
- {
- char *answer;
-
- tty_printf(_("How carefully have you verified the key you are "
- "about to sign actually belongs\nto the person named "
- "above? If you don't know what to answer, enter \"0\".\n"));
- tty_printf("\n");
- tty_printf(_(" (0) I will not answer.%s\n"),
- opt.def_cert_check_level==0?_(" (default)"):"");
- tty_printf(_(" (1) I have not checked at all.%s\n"),
- opt.def_cert_check_level==1?_(" (default)"):"");
- tty_printf(_(" (2) I have done casual checking.%s\n"),
- opt.def_cert_check_level==2?_(" (default)"):"");
- tty_printf(_(" (3) I have done very careful checking.%s\n"),
- opt.def_cert_check_level==3?_(" (default)"):"");
- tty_printf("\n");
-
- while(class==0)
- {
- answer = cpr_get("sign_uid.class",_("Your selection? "));
-
- if(answer[0]=='\0')
- class=0x10+opt.def_cert_check_level; /* Default */
- else if(ascii_strcasecmp(answer,"0")==0)
- class=0x10; /* Generic */
- else if(ascii_strcasecmp(answer,"1")==0)
- class=0x11; /* Persona */
- else if(ascii_strcasecmp(answer,"2")==0)
- class=0x12; /* Casual */
- else if(ascii_strcasecmp(answer,"3")==0)
- class=0x13; /* Positive */
- else
- tty_printf(_("Invalid selection.\n"));
-
- m_free(answer);
- }
- }
-
- tty_printf(_("Are you really sure that you want to sign this key\n"
- "with your key: \""));
- p = get_user_id( sk_keyid, &n );
- tty_print_utf8_string( p, n );
- m_free(p); p = NULL;
- tty_printf("\"\n");
-
- if(selfsig)
- {
- tty_printf(_("\nThis will be a self-signature.\n"));
-
- if( local )
- tty_printf(
- _("\nWARNING: the signature will not be marked "
- "as non-exportable.\n"));
-
- if( nonrevocable )
- tty_printf(
- _("\nWARNING: the signature will not be marked "
- "as non-revocable.\n"));
- }
- else
- {
- if( local )
- tty_printf(
- _("\nThe signature will be marked as non-exportable.\n"));
-
- if( nonrevocable )
- tty_printf(
- _("\nThe signature will be marked as non-revocable.\n"));
-
- switch(class)
- {
- case 0x11:
- tty_printf(_("\nI have not checked this key at all.\n"));
- break;
-
- case 0x12:
- tty_printf(_("\nI have checked this key casually.\n"));
- break;
-
- case 0x13:
- tty_printf(_("\nI have checked this key very carefully.\n"));
- break;
- }
- }
-
- tty_printf("\n");
-
- if( opt.batch && opt.answer_yes )
- ;
- else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
- continue;
-
- /* now we can sign the user ids */
- reloop: /* (must use this, because we are modifing the list) */
- primary_pk = NULL;
- for( node=keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY )
- primary_pk = node->pkt->pkt.public_key;
- else if( node->pkt->pkttype == PKT_USER_ID
- && (node->flag & NODFLG_MARK_A) ) {
- PACKET *pkt;
- PKT_signature *sig;
- struct sign_attrib attrib;
-
- assert( primary_pk );
- memset( &attrib, 0, sizeof attrib );
- attrib.non_exportable = local;
- attrib.non_revocable = nonrevocable;
- node->flag &= ~NODFLG_MARK_A;
-
- /* we force creation of a v4 signature for local
- * signatures, otherwise we would not generate the
- * subpacket with v3 keys and the signature becomes
- * exportable */
-
- if(selfsig)
- rc = make_keysig_packet( &sig, primary_pk,
- node->pkt->pkt.user_id,
- NULL,
- sk,
- 0x13, 0, force_v4?4:0, 0, 0,
- keygen_add_std_prefs, primary_pk);
- else
- rc = make_keysig_packet( &sig, primary_pk,
- node->pkt->pkt.user_id,
- NULL,
- sk,
- class, 0, force_v4?4:0,
- timestamp, duration,
- sign_mk_attrib, &attrib );
- if( rc ) {
- log_error(_("signing failed: %s\n"), g10_errstr(rc));
- goto leave;
- }
-
- *ret_modified = 1; /* we changed the keyblock */
- update_trust = 1;
-
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = sig;
- insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
- goto reloop;
- }
- }
-
- /* Delete any sigs that got promoted */
- for( node=keyblock; node; node = node->next )
- if( node->flag & NODFLG_DELSIG)
- delete_kbnode(node);
- } /* end loop over signators */
-
- leave:
- release_sk_list( sk_list );
- if( sk )
- free_secret_key(sk);
- return rc;
-}
-
-
-
-/****************
- * Change the passphrase of the primary and all secondary keys.
- * We use only one passphrase for all keys.
- */
-static int
-change_passphrase( KBNODE keyblock )
-{
- int rc = 0;
- int changed=0;
- KBNODE node;
- PKT_secret_key *sk;
- char *passphrase = NULL;
- int no_primary_secrets = 0;
-
- node = find_kbnode( keyblock, PKT_SECRET_KEY );
- if( !node ) {
- log_error("Oops; secret key not found anymore!\n");
- goto leave;
- }
- sk = node->pkt->pkt.secret_key;
-
- switch( is_secret_key_protected( sk ) ) {
- case -1:
- rc = G10ERR_PUBKEY_ALGO;
- break;
- case 0:
- tty_printf(_("This key is not protected.\n"));
- break;
- default:
- if( sk->protect.s2k.mode == 1001 ) {
- tty_printf(_("Secret parts of primary key are not available.\n"));
- no_primary_secrets = 1;
- }
- else {
- tty_printf(_("Key is protected.\n"));
- rc = check_secret_key( sk, 0 );
- if( !rc )
- passphrase = get_last_passphrase();
- }
- break;
- }
-
- /* unprotect all subkeys (use the supplied passphrase or ask)*/
- for(node=keyblock; !rc && node; node = node->next ) {
- if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- PKT_secret_key *subsk = node->pkt->pkt.secret_key;
- set_next_passphrase( passphrase );
- rc = check_secret_key( subsk, 0 );
- if( !rc && !passphrase )
- passphrase = get_last_passphrase();
- }
- }
-
- if( rc )
- tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
- else {
- DEK *dek = NULL;
- STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
- const char *errtext = NULL;
-
- tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
-
- set_next_passphrase( NULL );
- for(;;) {
- s2k->mode = opt.s2k_mode;
- s2k->hash_algo = opt.s2k_digest_algo;
- dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
- s2k, 2, errtext);
- if( !dek ) {
- errtext = _("passphrase not correctly repeated; try again");
- tty_printf ("%s.\n", errtext);
- }
- else if( !dek->keylen ) {
- rc = 0;
- tty_printf(_( "You don't want a passphrase -"
- " this is probably a *bad* idea!\n\n"));
- if( cpr_get_answer_is_yes("change_passwd.empty.okay",
- _("Do you really want to do this? ")))
- changed++;
- break;
- }
- else { /* okay */
- rc = 0;
- if( !no_primary_secrets ) {
- sk->protect.algo = dek->algo;
- sk->protect.s2k = *s2k;
- rc = protect_secret_key( sk, dek );
- }
- for(node=keyblock; !rc && node; node = node->next ) {
- if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- PKT_secret_key *subsk = node->pkt->pkt.secret_key;
- subsk->protect.algo = dek->algo;
- subsk->protect.s2k = *s2k;
- rc = protect_secret_key( subsk, dek );
- }
- }
- if( rc )
- log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
- else
- changed++;
- break;
- }
- }
- m_free(s2k);
- m_free(dek);
- }
-
- leave:
- m_free( passphrase );
- set_next_passphrase( NULL );
- return changed && !rc;
-}
-
-
-/****************
- * There are some keys out (due to a bug in gnupg), where the sequence
- * of the packets is wrong. This function fixes that.
- * Returns: true if the keyblock has been fixed.
- *
- * Note: This function does not work if there is more than one user ID.
- */
-static int
-fix_keyblock( KBNODE keyblock )
-{
- KBNODE node, last, subkey;
- int fixed=0;
-
- /* locate key signatures of class 0x10..0x13 behind sub key packets */
- for( subkey=last=NULL, node = keyblock; node;
- last=node, node = node->next ) {
- switch( node->pkt->pkttype ) {
- case PKT_PUBLIC_SUBKEY:
- case PKT_SECRET_SUBKEY:
- if( !subkey )
- subkey = last; /* actually it is the one before the subkey */
- break;
- case PKT_SIGNATURE:
- if( subkey ) {
- PKT_signature *sig = node->pkt->pkt.signature;
- if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
- log_info(_(
- "moving a key signature to the correct place\n"));
- last->next = node->next;
- node->next = subkey->next;
- subkey->next = node;
- node = last;
- fixed=1;
- }
- }
- break;
- default: break;
- }
- }
-
- return fixed;
-}
-
-/****************
- * Menu driven key editor. If sign_mode is true semi-automatical signing
- * will be performed. commands are ignore in this case
- *
- * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
- */
-
-void
-keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
- int sign_mode )
-{
- enum cmdids { cmdNONE = 0,
- cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
- cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG,
- cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID,
- cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY,
- cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY,
- cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, cmdINVCMD,
- cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP };
- static struct { const char *name;
- enum cmdids id;
- int need_sk;
- int not_with_sk;
- int signmode;
- const char *desc;
- } cmds[] = {
- { N_("quit") , cmdQUIT , 0,0,1, N_("quit this menu") },
- { N_("q") , cmdQUIT , 0,0,1, NULL },
- { N_("save") , cmdSAVE , 0,0,1, N_("save and quit") },
- { N_("help") , cmdHELP , 0,0,1, N_("show this help") },
- { "?" , cmdHELP , 0,0,1, NULL },
- { N_("fpr") , cmdFPR , 0,0,1, N_("show fingerprint") },
- { N_("list") , cmdLIST , 0,0,1, N_("list key and user IDs") },
- { N_("l") , cmdLIST , 0,0,1, NULL },
- { N_("uid") , cmdSELUID , 0,0,1, N_("select user ID N") },
- { N_("key") , cmdSELKEY , 0,0,0, N_("select secondary key N") },
- { N_("check") , cmdCHECK , 0,0,1, N_("list signatures") },
- { N_("c") , cmdCHECK , 0,0,1, NULL },
- { N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") },
- { N_("s") , cmdSIGN , 0,1,1, NULL },
- { N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") },
- { N_("nrsign") , cmdNRSIGN , 0,1,1, N_("sign the key non-revocably") },
- { N_("nrlsign") , cmdNRLSIGN , 0,1,1, N_("sign the key locally and non-revocably") },
- { N_("debug") , cmdDEBUG , 0,0,0, NULL },
- { N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
- { N_("addphoto"), cmdADDPHOTO , 1,1,0, N_("add a photo ID") },
- { N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") },
- /* delphoto is really deluid in disguise */
- { N_("delphoto"), cmdDELUID , 0,1,0, NULL },
- { N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },
- { N_("delkey") , cmdDELKEY , 0,1,0, N_("delete a secondary key") },
- { N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") },
- { N_("delsig") , cmdDELSIG , 0,1,0, N_("delete signatures") },
- { N_("expire") , cmdEXPIRE , 1,1,0, N_("change the expire date") },
- { N_("primary") , cmdPRIMARY , 1,1,0, N_("flag user ID as primary")},
- { N_("toggle") , cmdTOGGLE , 1,0,0, N_("toggle between secret "
- "and public key listing") },
- { N_("t" ) , cmdTOGGLE , 1,0,0, NULL },
- { N_("pref") , cmdPREF , 0,1,0, N_("list preferences (expert)") },
- { 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_("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") },
- { N_("revkey") , cmdREVKEY , 1,1,0, N_("revoke a secondary key") },
- { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
- { N_("enable") , cmdENABLEKEY , 0,1,0, N_("enable a key") },
- { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") },
-
- { NULL, cmdNONE } };
- enum cmdids cmd = 0;
- int rc = 0;
- KBNODE keyblock = NULL;
- KEYDB_HANDLE kdbhd = NULL;
- KBNODE sec_keyblock = NULL;
- KEYDB_HANDLE sec_kdbhd = NULL;
- KBNODE cur_keyblock;
- char *answer = NULL;
- int redisplay = 1;
- int modified = 0;
- int sec_modified = 0;
- int toggle;
- int have_commands = !!commands;
-
- if ( opt.command_fd != -1 )
- ;
- else if( opt.batch && !have_commands ) {
- log_error(_("can't do that in batchmode\n"));
- goto leave;
- }
-
- if( sign_mode ) {
- commands = NULL;
- append_to_strlist( &commands, sign_mode == 1? "sign":
- sign_mode == 2?"lsign":
- sign_mode == 3?"nrsign":"nrlsign");
- have_commands = 1;
- }
-
- /* get the public key */
- rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd);
- if( rc )
- goto leave;
- if( fix_keyblock( keyblock ) )
- modified++;
- if( collapse_uids( &keyblock ) )
- modified++;
-
- if( !sign_mode ) {/* see whether we have a matching secret key */
- PKT_public_key *pk = keyblock->pkt->pkt.public_key;
-
- sec_kdbhd = keydb_new (1);
- {
- byte afp[MAX_FINGERPRINT_LEN];
- size_t an;
-
- fingerprint_from_pk (pk, afp, &an);
- while (an < MAX_FINGERPRINT_LEN)
- afp[an++] = 0;
- rc = keydb_search_fpr (sec_kdbhd, afp);
- }
- if (!rc) {
- rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock);
- if (rc) {
- log_error (_("error reading secret keyblock `%s': %s\n"),
- username, g10_errstr(rc));
- }
- else {
- merge_keys_and_selfsig( sec_keyblock );
- if( fix_keyblock( sec_keyblock ) )
- sec_modified++;
- }
- }
-
- if (rc) {
- sec_keyblock = NULL;
- keydb_release (sec_kdbhd); sec_kdbhd = NULL;
- rc = 0;
- }
- }
-
- if( sec_keyblock ) {
- tty_printf(_("Secret key is available.\n"));
- }
-
- toggle = 0;
- cur_keyblock = keyblock;
- for(;;) { /* main loop */
- int i, arg_number, photo;
- const char *arg_string = "";
- char *p;
- PKT_public_key *pk=keyblock->pkt->pkt.public_key;
-
- tty_printf("\n");
- if( redisplay ) {
- show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
- tty_printf("\n");
- redisplay = 0;
- }
- do {
- m_free(answer);
- if( have_commands ) {
- if( commands ) {
- answer = m_strdup( commands->d );
- commands = commands->next;
- }
- else if( opt.batch ) {
- answer = m_strdup("quit");
- }
- else
- have_commands = 0;
- }
- if( !have_commands ) {
- answer = cpr_get_no_help("keyedit.prompt", _("Command> "));
- cpr_kill_prompt();
- }
- trim_spaces(answer);
- } while( *answer == '#' );
-
- arg_number = 0; /* Yes, here is the init which egcc complains about */
- photo = 0; /* This too */
- if( !*answer )
- cmd = cmdLIST;
- else if( *answer == CONTROL_D )
- cmd = cmdQUIT;
- else if( isdigit( *answer ) ) {
- cmd = cmdSELUID;
- arg_number = atoi(answer);
- }
- else {
- if( (p=strchr(answer,' ')) ) {
- *p++ = 0;
- trim_spaces(answer);
- trim_spaces(p);
- arg_number = atoi(p);
- arg_string = p;
- }
-
- for(i=0; cmds[i].name; i++ ) {
- if( !ascii_strcasecmp( answer, cmds[i].name ) )
- break;
- }
- if( sign_mode && !cmds[i].signmode )
- cmd = cmdINVCMD;
- else if( cmds[i].need_sk && !sec_keyblock ) {
- tty_printf(_("Need the secret key to do this.\n"));
- cmd = cmdNOP;
- }
- else if( cmds[i].not_with_sk && sec_keyblock && toggle ) {
- tty_printf(_("Please use the command \"toggle\" first.\n"));
- cmd = cmdNOP;
- }
- else
- cmd = cmds[i].id;
- }
- switch( cmd ) {
- case cmdHELP:
- for(i=0; cmds[i].name; i++ ) {
- if( sign_mode && !cmds[i].signmode )
- ;
- else if( cmds[i].need_sk && !sec_keyblock )
- ; /* skip if we do not have the secret key */
- else if( cmds[i].desc )
- tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
- }
- break;
-
- case cmdLIST:
- redisplay = 1;
- break;
-
- case cmdFPR:
- show_key_and_fingerprint( keyblock );
- break;
-
- case cmdSELUID:
- if( menu_select_uid( cur_keyblock, arg_number ) )
- redisplay = 1;
- break;
-
- case cmdSELKEY:
- if( menu_select_key( cur_keyblock, arg_number ) )
- redisplay = 1;
- break;
-
- case cmdCHECK:
- /* we can only do this with the public key becuase the
- * check functions can't cope with secret keys and it
- * is questionable whether this would make sense at all */
- check_all_keysigs( keyblock, count_selected_uids(keyblock) );
- break;
-
- case cmdSIGN: /* sign (only the public key) */
- case cmdLSIGN: /* sign (only the public key) */
- case cmdNRSIGN: /* sign (only the public key) */
- case cmdNRLSIGN: /* sign (only the public key) */
- if( pk->is_revoked )
- {
- tty_printf(_("Key is revoked."));
-
- if(opt.expert)
- {
- tty_printf(" ");
- if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay",
- _("Are you sure you still want "
- "to sign it? (y/N) ")))
- break;
- }
- else
- {
- tty_printf(_(" Unable to sign.\n"));
- break;
- }
- }
-
- if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
- if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
- _("Really sign all user IDs? ")) ) {
- tty_printf(_("Hint: Select the user IDs to sign\n"));
- break;
- }
- }
- if( !sign_uids( keyblock, locusr, &modified,
- (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN),
- (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN))
- && sign_mode )
- goto do_cmd_save;
- break;
-
- case cmdDEBUG:
- dump_kbnode( cur_keyblock );
- break;
-
- case cmdTOGGLE:
- toggle = !toggle;
- cur_keyblock = toggle? sec_keyblock : keyblock;
- redisplay = 1;
- break;
-
- case cmdADDPHOTO:
- if (opt.rfc2440 || opt.rfc1991 || opt.pgp2)
- {
- tty_printf(
- _("This command is not allowed while in %s mode.\n"),
- opt.rfc2440?"OpenPGP":opt.pgp2?"PGP2":"RFC-1991");
- break;
- }
- photo=1;
- /* fall through */
-
- case cmdADDUID:
- if( menu_adduid( keyblock, sec_keyblock, photo ) ) {
- redisplay = 1;
- sec_modified = modified = 1;
- merge_keys_and_selfsig( sec_keyblock );
- merge_keys_and_selfsig( keyblock );
- }
- break;
-
- case cmdDELUID: {
- int n1;
-
- if( !(n1=count_selected_uids(keyblock)) )
- tty_printf(_("You must select at least one user ID.\n"));
- else if( real_uids_left(keyblock) < 1 )
- tty_printf(_("You can't delete the last user ID!\n"));
- else if( cpr_get_answer_is_yes(
- "keyedit.remove.uid.okay",
- n1 > 1? _("Really remove all selected user IDs? ")
- : _("Really remove this user ID? ")
- ) ) {
- menu_deluid( keyblock, sec_keyblock );
- redisplay = 1;
- modified = 1;
- if( sec_keyblock )
- sec_modified = 1;
- }
- }
- break;
-
- case cmdDELSIG: {
- int n1;
-
- if( !(n1=count_selected_uids(keyblock)) )
- tty_printf(_("You must select at least one user ID.\n"));
- else if( menu_delsig( keyblock ) ) {
- /* no redisplay here, because it may scroll away some
- * status output of delsig */
- modified = 1;
- }
- }
- break;
-
- case cmdADDKEY:
- if( generate_subkeypair( keyblock, sec_keyblock ) ) {
- redisplay = 1;
- sec_modified = modified = 1;
- merge_keys_and_selfsig( sec_keyblock );
- merge_keys_and_selfsig( keyblock );
- }
- break;
-
-
- case cmdDELKEY: {
- int n1;
-
- if( !(n1=count_selected_keys( keyblock )) )
- tty_printf(_("You must select at least one key.\n"));
- else if( sec_keyblock && !cpr_get_answer_is_yes(
- "keyedit.remove.subkey.okay",
- n1 > 1?
- _("Do you really want to delete the selected keys? "):
- _("Do you really want to delete this key? ")
- ))
- ;
- else {
- menu_delkey( keyblock, sec_keyblock );
- redisplay = 1;
- modified = 1;
- if( sec_keyblock )
- sec_modified = 1;
- }
- }
- break;
-
- case cmdADDREVOKER:
- {
- int sensitive=0;
-
- if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0)
- sensitive=1;
- if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
- redisplay = 1;
- sec_modified = modified = 1;
- merge_keys_and_selfsig( sec_keyblock );
- merge_keys_and_selfsig( keyblock );
- }
- }
- break;
-
- case cmdREVKEY: {
- int n1;
-
- if( !(n1=count_selected_keys( keyblock )) )
- tty_printf(_("You must select at least one key.\n"));
- else if( sec_keyblock && !cpr_get_answer_is_yes(
- "keyedit.revoke.subkey.okay",
- n1 > 1?
- _("Do you really want to revoke the selected keys? "):
- _("Do you really want to revoke this key? ")
- ))
- ;
- else {
- if( menu_revkey( keyblock, sec_keyblock ) ) {
- modified = 1;
- /*sec_modified = 1;*/
- }
- redisplay = 1;
- }
- }
- break;
-
- case cmdEXPIRE:
- if( menu_expire( keyblock, sec_keyblock ) ) {
- merge_keys_and_selfsig( sec_keyblock );
- merge_keys_and_selfsig( keyblock );
- sec_modified = 1;
- modified = 1;
- redisplay = 1;
- }
- break;
-
- case cmdPRIMARY:
- if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
- merge_keys_and_selfsig( keyblock );
- modified = 1;
- redisplay = 1;
- }
- break;
-
- case cmdPASSWD:
- if( change_passphrase( sec_keyblock ) )
- sec_modified = 1;
- break;
-
- case cmdTRUST:
- show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 );
- tty_printf("\n");
- if( edit_ownertrust( find_kbnode( keyblock,
- PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) ) {
- redisplay = 1;
- /* No real need to set update_trust here as
- edit_ownertrust() calls revalidation_mark()
- anyway. */
- update_trust=1;
- }
- break;
-
- case cmdPREF:
- show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 );
- break;
-
- case cmdSHOWPREF:
- show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 );
- break;
-
- case cmdSETPREF:
- keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0);
- break;
-
- case cmdUPDPREF:
- {
- p = keygen_get_std_prefs ();
- tty_printf (("Current preference list: %s\n"), p);
- m_free (p);
- }
- if (cpr_get_answer_is_yes ("keyedit.updpref.okay",
- count_selected_uids (keyblock)?
- _("Really update the preferences"
- " for the selected user IDs? "):
- _("Really update the preferences? "))){
-
- if ( menu_set_preferences (keyblock, sec_keyblock) ) {
- merge_keys_and_selfsig (keyblock);
- modified = 1;
- redisplay = 1;
- }
- }
- break;
-
- case cmdNOP:
- break;
-
- case cmdREVSIG:
- if( menu_revsig( keyblock ) ) {
- redisplay = 1;
- modified = 1;
- }
- break;
-
- case cmdENABLEKEY:
- case cmdDISABLEKEY:
- if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) {
- redisplay = 1;
- modified = 1;
- }
- break;
-
- case cmdSHOWPHOTO:
- menu_showphoto(keyblock);
- break;
-
- case cmdQUIT:
- if( have_commands )
- goto leave;
- if( !modified && !sec_modified )
- goto leave;
- if( !cpr_get_answer_is_yes("keyedit.save.okay",
- _("Save changes? ")) ) {
- if( cpr_enabled()
- || cpr_get_answer_is_yes("keyedit.cancel.okay",
- _("Quit without saving? ")) )
- goto leave;
- break;
- }
- /* fall thru */
- case cmdSAVE:
- do_cmd_save:
- if( modified || sec_modified ) {
- if( modified ) {
- rc = keydb_update_keyblock (kdbhd, keyblock);
- if( rc ) {
- log_error(_("update failed: %s\n"), g10_errstr(rc) );
- break;
- }
- }
- if( sec_modified ) {
- rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock );
- if( rc ) {
- log_error( _("update secret failed: %s\n"),
- g10_errstr(rc) );
- break;
- }
- }
- }
- else
- tty_printf(_("Key not changed so no update needed.\n"));
-
- if( update_trust )
- {
- revalidation_mark ();
- update_trust=0;
- }
- goto leave;
-
- case cmdINVCMD:
- default:
- tty_printf("\n");
- tty_printf(_("Invalid command (try \"help\")\n"));
- break;
- }
- } /* end main loop */
-
- leave:
- release_kbnode( keyblock );
- release_kbnode( sec_keyblock );
- keydb_release (kdbhd);
- m_free(answer);
-}
-
-
-/****************
- * show preferences of a public keyblock.
- */
-static void
-show_prefs (PKT_user_id *uid, int verbose)
-{
- const prefitem_t fake={0,0};
- const prefitem_t *prefs;
- int i;
-
- if( !uid )
- return;
-
- if( uid->prefs )
- prefs=uid->prefs;
- else if(verbose)
- prefs=&fake;
- else
- return;
-
- if (verbose) {
- int any, des_seen=0, sha1_seen=0, uncomp_seen=0;
- tty_printf (" Cipher: ");
- for(i=any=0; prefs[i].type; i++ ) {
- if( prefs[i].type == PREFTYPE_SYM ) {
- const char *s = cipher_algo_to_string (prefs[i].value);
-
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (s && prefs[i].value < 100 )
- tty_printf ("%s", s );
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == CIPHER_ALGO_3DES )
- des_seen = 1;
- }
- }
- if (!des_seen) {
- if (any)
- tty_printf (", ");
- tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES));
- }
- tty_printf ("\n Hash: ");
- for(i=any=0; prefs[i].type; i++ ) {
- if( prefs[i].type == PREFTYPE_HASH ) {
- const char *s = digest_algo_to_string (prefs[i].value);
-
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (s && prefs[i].value < 100 )
- tty_printf ("%s", s );
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == DIGEST_ALGO_SHA1 )
- sha1_seen = 1;
- }
- }
- if (!sha1_seen) {
- if (any)
- tty_printf (", ");
- tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1));
- }
- tty_printf ("\n Compression: ");
- for(i=any=0; prefs[i].type; i++ ) {
- if( prefs[i].type == PREFTYPE_ZIP ) {
- const char *s=compress_algo_to_string(prefs[i].value);
-
- if (any)
- tty_printf (", ");
- any = 1;
- /* We don't want to display strings for experimental algos */
- if (s && prefs[i].value < 100 )
- tty_printf ("%s", s );
- else
- tty_printf ("[%d]", prefs[i].value);
- if (prefs[i].value == 0 )
- uncomp_seen = 1;
- }
- }
- if (!uncomp_seen) {
- if (any)
- tty_printf (", ");
- else {
- tty_printf ("%s",compress_algo_to_string(1));
- tty_printf (", ");
- }
- tty_printf ("%s",compress_algo_to_string(0));
- }
- tty_printf ("\n Features: ");
- if(uid->mdc_feature)
- tty_printf ("MDC");
- tty_printf("\n");
- }
- else {
- tty_printf(" ");
- for(i=0; prefs[i].type; i++ ) {
- tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
- prefs[i].type == PREFTYPE_HASH ? 'H' :
- prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
- prefs[i].value);
- }
- if (uid->mdc_feature)
- tty_printf (" [mdc]");
- tty_printf("\n");
- }
-}
-
-
-/* This is the version of show_key_with_all_names used when
- opt.with_colons is used. It prints all available data in a easy to
- parse format and does not translate utf8 */
-static void
-show_key_with_all_names_colon (KBNODE keyblock)
-{
- KBNODE node;
- int i, j;
- byte pk_version=0;
-
- /* the keys */
- 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;
- int otrust=0, trust=0;
- u32 keyid[2];
-
- if (node->pkt->pkttype == PKT_PUBLIC_KEY)
- {
- trust = get_validity_info (pk, NULL);
- otrust = get_ownertrust_info (pk);
- pk_version = pk->version;
- }
-
- keyid_from_pk (pk, keyid);
-
- fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout);
- if (!pk->is_valid)
- putchar ('i');
- else if (pk->is_revoked)
- putchar ('r');
- else if (pk->has_expired)
- putchar ('e');
- else
- putchar (trust);
- printf (":%u:%d:%08lX%08lX:%lu:%lu:",
- nbits_from_pk (pk),
- pk->pubkey_algo,
- (ulong)keyid[0], (ulong)keyid[1],
- (ulong)pk->timestamp,
- (ulong)pk->expiredate );
- if (pk->local_id)
- printf ("%lu", pk->local_id);
- putchar (':');
- putchar (otrust);
- putchar(':');
- putchar('\n');
-
- print_fingerprint (pk, NULL, 0);
-
- /* print the revoker record */
- if( !pk->revkey && pk->numrevkeys )
- BUG();
- else
- {
- for (i=0; i < pk->numrevkeys; i++)
- {
- byte *p;
-
- printf ("rvk:::%d::::::", pk->revkey[i].algid);
- p = pk->revkey[i].fpr;
- for (j=0; j < 20; j++, p++ )
- printf ("%02X", *p);
- printf (":%02x%s:\n", pk->revkey[i].class,
- (pk->revkey[i].class&0x40)?"s":"");
- }
- }
- }
- }
-
- /* the user ids */
- i = 0;
- for (node = keyblock; node; node = node->next)
- {
- if ( node->pkt->pkttype == PKT_USER_ID )
- {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- int trustletter = '?';
-
- ++i;
- if(uid->attrib_data)
- {
- printf ("uat:%c::::::::%u %lu", trustletter,
- uid->numattribs,uid->attrib_len);
- }
- else
- {
- printf ("uid:%c::::::::", trustletter);
- print_string (stdout, uid->name, uid->len, ':');
- }
- putchar (':');
- /* signature class */
- putchar (':');
- /* capabilities */
- putchar (':');
- /* preferences */
- if (pk_version>3 || uid->selfsigversion>3)
- {
- const prefitem_t *prefs = uid->prefs;
-
- for (j=0; prefs && prefs[j].type; j++)
- {
- if (j)
- putchar (' ');
- printf ("%c%d", prefs[j].type == PREFTYPE_SYM ? 'S' :
- prefs[j].type == PREFTYPE_HASH ? 'H' :
- prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
- prefs[j].value);
- }
- if (uid->mdc_feature)
- printf (",mdc");
- }
- putchar (':');
- /* flags */
- printf ("%d,", i);
- if (uid->is_primary)
- putchar ('p');
- if (uid->is_revoked)
- putchar ('r');
- if (uid->is_expired)
- putchar ('e');
- if ((node->flag & NODFLG_SELUID))
- putchar ('s');
- if ((node->flag & NODFLG_MARK_A))
- putchar ('m');
- putchar (':');
- putchar('\n');
- }
- }
-}
-
-
-/****************
- * Display the key a the user ids, if only_marked is true, do only
- * so for user ids with mark A flag set and dont display the index number
- */
-static void
-show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
- int with_fpr, int with_subkeys, int with_prefs )
-{
- KBNODE node;
- int i, rc;
- int do_warn = 0;
- byte pk_version=0;
-
- if (opt.with_colons)
- {
- show_key_with_all_names_colon (keyblock);
- return;
- }
-
- /* the keys */
- for( node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY
- || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
- PKT_public_key *pk = node->pkt->pkt.public_key;
- int otrust=0, trust=0;
-
- if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- /* do it here, so that debug messages don't clutter the
- * output */
- static int did_warn = 0;
-
- trust = get_validity_info (pk, NULL);
- otrust = get_ownertrust_info (pk);
-
- /* Show a warning once */
- if (!did_warn
- && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) {
- did_warn = 1;
- do_warn = 1;
- }
-
- pk_version=pk->version;
- }
-
- if(with_revoker) {
- if( !pk->revkey && pk->numrevkeys )
- BUG();
- else
- for(i=0;i<pk->numrevkeys;i++) {
- u32 r_keyid[2];
- char *user;
-
- keyid_from_fingerprint(pk->revkey[i].fpr,
- MAX_FINGERPRINT_LEN,r_keyid);
-
- user=get_user_id_string (r_keyid);
- tty_printf (_("This key may be revoked by %s key "),
- pubkey_algo_to_string (pk->revkey[i].algid));
- tty_print_utf8_string (user, strlen (user));
- if ((pk->revkey[i].class&0x40))
- tty_printf (_(" (sensitive)"));
- tty_printf ("\n");
- m_free(user);
- }
- }
-
- tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
- node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
- (node->flag & NODFLG_SELKEY)? '*':' ',
- nbits_from_pk( pk ),
- pubkey_letter( pk->pubkey_algo ),
- (ulong)keyid_from_pk(pk,NULL),
- datestr_from_pk(pk),
- expirestr_from_pk(pk) );
- if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- tty_printf(_(" trust: %c/%c"), otrust, trust );
- if( node->pkt->pkttype == PKT_PUBLIC_KEY
- && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) {
- tty_printf("\n*** ");
- tty_printf(_("This key has been disabled"));
- }
-
- if( with_fpr ) {
- tty_printf("\n");
- print_fingerprint ( pk, NULL, 2 );
- }
- }
- tty_printf("\n");
- }
- else if( node->pkt->pkttype == PKT_SECRET_KEY
- || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
- PKT_secret_key *sk = node->pkt->pkt.secret_key;
- tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
- node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
- (node->flag & NODFLG_SELKEY)? '*':' ',
- nbits_from_sk( sk ),
- pubkey_letter( sk->pubkey_algo ),
- (ulong)keyid_from_sk(sk,NULL),
- datestr_from_sk(sk),
- expirestr_from_sk(sk) );
- tty_printf("\n");
- }
- else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
- && node->pkt->pkt.signature->sig_class == 0x28 ) {
- PKT_signature *sig = node->pkt->pkt.signature;
-
- rc = check_key_signature( keyblock, node, NULL );
- if( !rc )
- tty_printf( _("rev! subkey has been revoked: %s\n"),
- datestr_from_sig( sig ) );
- else if( rc == G10ERR_BAD_SIGN )
- tty_printf( _("rev- faked revocation found\n") );
- else if( rc )
- tty_printf( _("rev? problem checking revocation: %s\n"),
- g10_errstr(rc) );
- }
- }
- /* the user ids */
- i = 0;
- for( node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- ++i;
- if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
- if( only_marked )
- tty_printf(" ");
- else if( node->flag & NODFLG_SELUID )
- tty_printf("(%d)* ", i);
- else if( uid->is_primary )
- tty_printf("(%d). ", i);
- else
- tty_printf("(%d) ", i);
- if ( uid->is_revoked )
- tty_printf ("[revoked] ");
- if ( uid->is_expired )
- tty_printf ("[expired] ");
- tty_print_utf8_string( uid->name, uid->len );
- tty_printf("\n");
- if( with_prefs )
- {
- if(pk_version>3 || uid->selfsigversion>3)
- show_prefs (uid, with_prefs == 2);
- else
- tty_printf(_("There are no preferences on a "
- "PGP 2.x-style user ID.\n"));
- }
- }
- }
- }
-
- if (do_warn)
- tty_printf (_("Please note that the shown key validity "
- "is not necessarily correct\n"
- "unless you restart the program.\n"));
-
-}
-
-
-/* Display basic key information. This fucntion is suitable to show
- information on the key without any dependencies on the trustdb or
- any other internal GnuPG stuff. KEYBLOCK may either be a public or
- a secret key.*/
-void
-show_basic_key_info ( KBNODE keyblock )
-{
- KBNODE node;
- int i;
-
- /* The primary key */
- for (node = keyblock; node; node = node->next)
- {
- if (node->pkt->pkttype == PKT_PUBLIC_KEY)
- {
- PKT_public_key *pk = node->pkt->pkt.public_key;
-
- /* Note, we use the same format string as in other show
- functions to make the translation job easier. */
- tty_printf (_("%s%c %4u%c/%08lX created: %s expires: %s"),
- node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
- ' ',
- nbits_from_pk( pk ),
- pubkey_letter( pk->pubkey_algo ),
- (ulong)keyid_from_pk(pk,NULL),
- datestr_from_pk(pk),
- expirestr_from_pk(pk) );
- tty_printf("\n");
- print_fingerprint ( pk, NULL, 3 );
- tty_printf("\n");
- }
- else if (node->pkt->pkttype == PKT_SECRET_KEY)
- {
- PKT_secret_key *sk = node->pkt->pkt.secret_key;
- tty_printf(_("%s%c %4u%c/%08lX created: %s expires: %s"),
- node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
- ' ',
- nbits_from_sk( sk ),
- pubkey_letter( sk->pubkey_algo ),
- (ulong)keyid_from_sk(sk,NULL),
- datestr_from_sk(sk),
- expirestr_from_sk(sk) );
- tty_printf("\n");
- print_fingerprint (NULL, sk, 3 );
- tty_printf("\n");
- }
- }
-
- /* The user IDs. */
- for (i=0, node = keyblock; node; node = node->next)
- {
- if (node->pkt->pkttype == PKT_USER_ID)
- {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- ++i;
-
- tty_printf (" ");
- if (uid->is_revoked)
- tty_printf ("[revoked] ");
- if ( uid->is_expired )
- tty_printf ("[expired] ");
- tty_print_utf8_string (uid->name, uid->len);
- tty_printf ("\n");
- }
- }
-}
-
-static void
-show_key_and_fingerprint( KBNODE keyblock )
-{
- KBNODE node;
- PKT_public_key *pk = NULL;
-
- for( node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- pk = node->pkt->pkt.public_key;
- tty_printf("pub %4u%c/%08lX %s ",
- nbits_from_pk( pk ),
- pubkey_letter( pk->pubkey_algo ),
- (ulong)keyid_from_pk(pk,NULL),
- datestr_from_pk(pk) );
- }
- else if( node->pkt->pkttype == PKT_USER_ID ) {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- tty_print_utf8_string( uid->name, uid->len );
- break;
- }
- }
- tty_printf("\n");
- if( pk )
- print_fingerprint( pk, NULL, 2 );
-}
-
-
-
-/****************
- * Ask for a new user id, do the selfsignature and put it into
- * both keyblocks.
- * Return true if there is a new user id
- */
-static int
-menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
-{
- PKT_user_id *uid;
- PKT_public_key *pk=NULL;
- PKT_secret_key *sk=NULL;
- PKT_signature *sig=NULL;
- PACKET *pkt;
- KBNODE node;
- KBNODE pub_where=NULL, sec_where=NULL;
- int rc;
-
- for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY )
- pk = node->pkt->pkt.public_key;
- else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
- break;
- }
- if( !node ) /* no subkey */
- pub_where = NULL;
- for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
- if( node->pkt->pkttype == PKT_SECRET_KEY )
- sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
- else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
- break;
- }
- if( !node ) /* no subkey */
- sec_where = NULL;
- assert(pk && sk);
-
- if(photo) {
- int hasattrib=0;
-
- for( node = pub_keyblock; node; node = node->next )
- if( node->pkt->pkttype == PKT_USER_ID &&
- node->pkt->pkt.user_id->attrib_data!=NULL)
- {
- hasattrib=1;
- break;
- }
-
- /* It is legal but bad for compatibility to add a photo ID to a
- v3 key as it means that PGP2 will not be able to use that key
- anymore. Also, PGP may not expect a photo on a v3 key.
- Don't bother to ask this if the key already has a photo - any
- damage has already been done at that point. -dms */
- if(pk->version==3 && !hasattrib)
- {
- if(opt.expert)
- {
- tty_printf(_("WARNING: This is a PGP2-style key. "
- "Adding a photo ID may cause some versions\n"
- " of PGP to reject this key.\n"));
-
- if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay",
- _("Are you sure you still want "
- "to add it? (y/N) ")))
- return 0;
- }
- else
- {
- tty_printf(_("You may not add a photo ID to "
- "a PGP2-style key.\n"));
- return 0;
- }
- }
-
- uid = generate_photo_id(pk);
- } else
- uid = generate_user_id();
- if( !uid )
- return 0;
-
- rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
- keygen_add_std_prefs, pk );
- free_secret_key( sk );
- if( rc ) {
- log_error("signing failed: %s\n", g10_errstr(rc) );
- free_user_id(uid);
- return 0;
- }
-
- /* insert/append to secret keyblock */
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_USER_ID;
- pkt->pkt.user_id = scopy_user_id(uid);
- node = new_kbnode(pkt);
- if( sec_where )
- insert_kbnode( sec_where, node, 0 );
- else
- add_kbnode( sec_keyblock, node );
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = copy_signature(NULL, sig);
- if( sec_where )
- insert_kbnode( node, new_kbnode(pkt), 0 );
- else
- add_kbnode( sec_keyblock, new_kbnode(pkt) );
- /* insert/append to public keyblock */
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_USER_ID;
- pkt->pkt.user_id = uid;
- node = new_kbnode(pkt);
- if( pub_where )
- insert_kbnode( pub_where, node, 0 );
- else
- add_kbnode( pub_keyblock, node );
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = copy_signature(NULL, sig);
- if( pub_where )
- insert_kbnode( node, new_kbnode(pkt), 0 );
- else
- add_kbnode( pub_keyblock, new_kbnode(pkt) );
- return 1;
-}
-
-
-/****************
- * Remove all selceted userids from the keyrings
- */
-static void
-menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
-{
- KBNODE node;
- int selected=0;
-
- for( node = pub_keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- selected = node->flag & NODFLG_SELUID;
- if( selected ) {
- /* Only cause a trust update if we delete a
- non-revoked user id */
- if(!node->pkt->pkt.user_id->is_revoked)
- update_trust=1;
- delete_kbnode( node );
- if( sec_keyblock ) {
- KBNODE snode;
- int s_selected = 0;
- PKT_user_id *uid = node->pkt->pkt.user_id;
- for( snode = sec_keyblock; snode; snode = snode->next ) {
- if( snode->pkt->pkttype == PKT_USER_ID ) {
- PKT_user_id *suid = snode->pkt->pkt.user_id;
-
- s_selected =
- (uid->len == suid->len
- && !memcmp( uid->name, suid->name, uid->len));
- if( s_selected )
- delete_kbnode( snode );
- }
- else if( s_selected
- && snode->pkt->pkttype == PKT_SIGNATURE )
- delete_kbnode( snode );
- else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
- s_selected = 0;
- }
- }
- }
- }
- else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
- delete_kbnode( node );
- else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
- selected = 0;
- }
- commit_kbnode( &pub_keyblock );
- if( sec_keyblock )
- commit_kbnode( &sec_keyblock );
-}
-
-
-static int
-menu_delsig( KBNODE pub_keyblock )
-{
- KBNODE node;
- PKT_user_id *uid = NULL;
- int changed=0;
-
- for( node = pub_keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
- }
- else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
- int okay, valid, selfsig, inv_sig, no_key, other_err;
-
- tty_printf("uid ");
- tty_print_utf8_string( uid->name, uid->len );
- tty_printf("\n");
-
- okay = inv_sig = no_key = other_err = 0;
- valid = print_and_check_one_sig( pub_keyblock, node,
- &inv_sig, &no_key, &other_err,
- &selfsig, 1 );
-
- if( valid ) {
- okay = cpr_get_answer_yes_no_quit(
- "keyedit.delsig.valid",
- _("Delete this good signature? (y/N/q)"));
-
- /* Only update trust if we delete a good signature.
- The other two cases do not affect trust. */
- if(okay)
- update_trust=1;
- }
- else if( inv_sig || other_err )
- okay = cpr_get_answer_yes_no_quit(
- "keyedit.delsig.invalid",
- _("Delete this invalid signature? (y/N/q)"));
- else if( no_key )
- okay = cpr_get_answer_yes_no_quit(
- "keyedit.delsig.unknown",
- _("Delete this unknown signature? (y/N/q)"));
-
- if( okay == -1 )
- break;
- if( okay && selfsig && !cpr_get_answer_is_yes(
- "keyedit.delsig.selfsig",
- _("Really delete this self-signature? (y/N)") ))
- okay = 0;
- if( okay ) {
- delete_kbnode( node );
- changed++;
- }
-
- }
- else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
- uid = NULL;
- }
-
- if( changed ) {
- commit_kbnode( &pub_keyblock );
- tty_printf( changed == 1? _("Deleted %d signature.\n")
- : _("Deleted %d signatures.\n"), changed );
- }
- else
- tty_printf( _("Nothing deleted.\n") );
-
- return changed;
-}
-
-
-/****************
- * Remove some of the secondary keys
- */
-static void
-menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
-{
- KBNODE node;
- int selected=0;
-
- for( node = pub_keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
- selected = node->flag & NODFLG_SELKEY;
- if( selected ) {
- delete_kbnode( node );
- if( sec_keyblock ) {
- KBNODE snode;
- int s_selected = 0;
- u32 ki[2];
-
- keyid_from_pk( node->pkt->pkt.public_key, ki );
- for( snode = sec_keyblock; snode; snode = snode->next ) {
- if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- u32 ki2[2];
-
- keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
- s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
- if( s_selected )
- delete_kbnode( snode );
- }
- else if( s_selected
- && snode->pkt->pkttype == PKT_SIGNATURE )
- delete_kbnode( snode );
- else
- s_selected = 0;
- }
- }
- }
- }
- else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
- delete_kbnode( node );
- else
- selected = 0;
- }
- commit_kbnode( &pub_keyblock );
- if( sec_keyblock )
- commit_kbnode( &sec_keyblock );
-
- /* No need to set update_trust here since signing keys no longer
- are used to certify other keys, so there is no change in trust
- when revoking/removing them */
-}
-
-
-/****************
- * Ask for a new revoker, do the selfsignature and put it into
- * both keyblocks.
- * Return true if there is a new revoker
- */
-static int
-menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
-{
- PKT_public_key *pk=NULL,*revoker_pk=NULL;
- PKT_secret_key *sk=NULL;
- PKT_signature *sig=NULL;
- PACKET *pkt;
- struct revocation_key revkey;
- size_t fprlen;
- int rc;
-
- assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
- assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
-
- pk=pub_keyblock->pkt->pkt.public_key;
-
- if(pk->numrevkeys==0 && pk->version==3)
- {
- /* It is legal but bad for compatibility to add a revoker to a
- v3 key as it means that PGP2 will not be able to use that key
- anymore. Also, PGP may not expect a revoker on a v3 key.
- Don't bother to ask this if the key already has a revoker -
- any damage has already been done at that point. -dms */
- if(opt.expert)
- {
- tty_printf(_("WARNING: This is a PGP 2.x-style key. "
- "Adding a designated revoker may cause\n"
- " some versions of PGP to reject this key.\n"));
-
- if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay",
- _("Are you sure you still want "
- "to add it? (y/N) ")))
- return 0;
- }
- else
- {
- tty_printf(_("You may not add a designated revoker to "
- "a PGP 2.x-style key.\n"));
- return 0;
- }
- }
-
- sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
-
- for(;;)
- {
- char *answer;
- u32 keyid[2];
- char *p;
- size_t n;
-
- if(revoker_pk)
- free_public_key(revoker_pk);
-
- revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
-
- tty_printf("\n");
-
- answer=cpr_get_utf8("keyedit.add_revoker",
- _("Enter the user ID of the designated revoker: "));
- if(answer[0]=='\0' || answer[0]=='\004')
- goto fail;
-
- rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL);
-
- if(rc)
- {
- log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
- continue;
- }
-
- fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
- if(fprlen!=20)
- {
- log_error(_("cannot appoint a PGP 2.x style key as a "
- "designated revoker\n"));
- continue;
- }
-
- revkey.class=0x80;
- if(sensitive)
- revkey.class|=0x40;
- revkey.algid=revoker_pk->pubkey_algo;
-
- if(cmp_public_keys(revoker_pk,pk)==0)
- {
- /* This actually causes no harm (after all, a key that
- designates itself as a revoker is the same as a
- regular key), but it's easy enough to check. */
- log_error(_("you cannot appoint a key as its own "
- "designated revoker\n"));
-
- continue;
- }
-
- keyid_from_pk(pk,NULL);
-
- /* Does this revkey already exist? */
- if(!pk->revkey && pk->numrevkeys)
- BUG();
- else
- {
- int i;
-
- for(i=0;i<pk->numrevkeys;i++)
- {
- if(memcmp(&pk->revkey[i],&revkey,
- sizeof(struct revocation_key))==0)
- {
- char buf[50];
-
- log_error(_("this key has already been designated "
- "as a revoker\n"));
-
- sprintf(buf,"%08lX%08lX",
- (ulong)pk->keyid[0],(ulong)pk->keyid[1]);
- write_status_text(STATUS_ALREADY_SIGNED,buf);
-
- break;
- }
- }
-
- if(i<pk->numrevkeys)
- continue;
- }
-
- keyid_from_pk(revoker_pk,keyid);
-
- tty_printf("\npub %4u%c/%08lX %s ",
- nbits_from_pk( revoker_pk ),
- pubkey_letter( revoker_pk->pubkey_algo ),
- (ulong)keyid[1], datestr_from_pk(pk) );
-
- p = get_user_id( keyid, &n );
- tty_print_utf8_string( p, n );
- m_free(p);
- tty_printf("\n");
- print_fingerprint(revoker_pk,NULL,2);
- tty_printf("\n");
-
- tty_printf("WARNING: appointing a key as a designated revoker "
- "cannot be undone!\n");
-
- tty_printf("\n");
-
- if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
- "Are you sure you want to appoint this "
- "key as a designated revoker? (y/N): "))
- continue;
-
- free_public_key(revoker_pk);
- revoker_pk=NULL;
- break;
- }
-
- /* The 1F signature must be at least v4 to carry the revocation key
- subpacket. */
- rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0,
- keygen_add_revkey,&revkey );
- if( rc )
- {
- log_error("signing failed: %s\n", g10_errstr(rc) );
- goto fail;
- }
-
- free_secret_key(sk);
- sk=NULL;
-
- /* insert into secret keyblock */
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = copy_signature(NULL, sig);
- insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
-
- /* insert into public keyblock */
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = sig;
- insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
-
- return 1;
-
- fail:
- if(sk)
- free_secret_key(sk);
- if(sig)
- free_seckey_enc(sig);
- if(revoker_pk)
- free_public_key(revoker_pk);
-
- return 0;
-}
-
-
-static int
-menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
-{
- int n1, signumber, rc;
- u32 expiredate;
- int mainkey=0;
- PKT_secret_key *sk; /* copy of the main sk */
- PKT_public_key *main_pk, *sub_pk;
- PKT_user_id *uid;
- KBNODE node;
- u32 keyid[2];
-
- if( count_selected_keys( sec_keyblock ) ) {
- tty_printf(_("Please remove selections from the secret keys.\n"));
- return 0;
- }
-
- n1 = count_selected_keys( pub_keyblock );
- if( n1 > 1 ) {
- tty_printf(_("Please select at most one secondary key.\n"));
- return 0;
- }
- else if( n1 )
- tty_printf(_("Changing expiration time for a secondary key.\n"));
- else {
- tty_printf(_("Changing expiration time for the primary key.\n"));
- mainkey=1;
- }
-
- expiredate = ask_expiredate();
- 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 = sub_pk = NULL;
- uid = NULL;
- signumber = 0;
- for( node=pub_keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
- main_pk = node->pkt->pkt.public_key;
- keyid_from_pk( main_pk, keyid );
- main_pk->expiredate = expiredate;
- }
- else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- && (node->flag & NODFLG_SELKEY ) ) {
- sub_pk = node->pkt->pkt.public_key;
- sub_pk->expiredate = expiredate;
- }
- else if( node->pkt->pkttype == PKT_USER_ID )
- uid = node->pkt->pkt.user_id;
- else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
- && ( mainkey || sub_pk ) ) {
- PKT_signature *sig = node->pkt->pkt.signature;
- if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
- && ( (mainkey && uid && (sig->sig_class&~3) == 0x10)
- || (!mainkey && sig->sig_class == 0x18) ) ) {
- /* this is a selfsignature which is to be replaced */
- PKT_signature *newsig;
- PACKET *newpkt;
- KBNODE sn;
- int signumber2 = 0;
-
- signumber++;
-
- if( (mainkey && main_pk->version < 4)
- || (!mainkey && sub_pk->version < 4 ) ) {
- log_info(_(
- "You can't change the expiration date of a v3 key\n"));
- free_secret_key( sk );
- return 0;
- }
-
- /* find the corresponding secret self-signature */
- for( sn=sec_keyblock; sn; sn = sn->next ) {
- if( sn->pkt->pkttype == PKT_SIGNATURE ) {
- PKT_signature *b = sn->pkt->pkt.signature;
- if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
- && sig->sig_class == b->sig_class
- && ++signumber2 == signumber )
- break;
- }
- }
- if( !sn )
- log_info(_("No corresponding signature in secret ring\n"));
-
- /* create new self signature */
- if( mainkey )
- rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
- sk, 0x13, 0, 0, 0, 0,
- keygen_add_std_prefs, main_pk );
- else
- rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
- sk, 0x18, 0, 0, 0, 0,
- keygen_add_key_expire, sub_pk );
- if( rc ) {
- log_error("make_keysig_packet failed: %s\n",
- g10_errstr(rc));
- 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;
- if( sn ) {
- newpkt = m_alloc_clear( sizeof *newpkt );
- newpkt->pkttype = PKT_SIGNATURE;
- newpkt->pkt.signature = copy_signature( NULL, newsig );
- free_packet( sn->pkt );
- m_free( sn->pkt );
- sn->pkt = newpkt;
- }
- sub_pk = NULL;
- }
- }
- }
-
- free_secret_key( sk );
- update_trust=1;
- return 1;
-}
-
-static int
-change_primary_uid_cb ( PKT_signature *sig, void *opaque )
-{
- byte buf[1];
-
- /* first clear all primary uid flags so that we are sure none are
- * lingering around */
- delete_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID);
- delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
-
- /* if opaque is set,we want to set the primary id */
- if (opaque) {
- buf[0] = 1;
- build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 );
- }
-
- return 0;
-}
-
-
-/*
- * Set the primary uid flag for the selected UID. We will also reset
- * all other primary uid flags. For this to work with have to update
- * all the signature timestamps. If we would do this with the current
- * time, we lose quite a lot of information, so we use a a kludge to
- * do this: Just increment the timestamp by one second which is
- * sufficient to updated a signature during import.
- */
-static int
-menu_set_primary_uid ( 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;
- int attribute = 0;
- int modified = 0;
-
- if ( count_selected_uids (pub_keyblock) != 1 ) {
- tty_printf(_("Please select exactly one user ID.\n"));
- return 0;
- }
-
- 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;
-
- /* Is our selected uid an attribute packet? */
- for ( node=pub_keyblock; node; node = node->next )
- if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
- attribute = (node->pkt->pkt.user_id->attrib_data!=NULL);
-
- 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 = node->flag & NODFLG_SELUID;
- }
- else if ( main_pk && uid && 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)
- && attribute == (uid->attrib_data!=NULL)) {
- 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 can just ignore v3 signatures because they are
- not able to carry the primary ID flag. We also
- ignore self-sigs on user IDs that are not of the
- same type that we are making primary. That is, if
- we are making a user ID primary, we alter user IDs.
- If we are making an attribute packet primary, we
- alter attribute packets. */
-
- /* FIXME: We must make sure that we only have one
- self-signature per user ID here (not counting
- revocations) */
- PKT_signature *newsig;
- PACKET *newpkt;
- const byte *p;
- int action;
-
- /* see whether this signature has the primary UID flag */
- p = parse_sig_subpkt (sig->hashed,
- SIGSUBPKT_PRIMARY_UID, NULL );
- if ( !p )
- p = parse_sig_subpkt (sig->unhashed,
- SIGSUBPKT_PRIMARY_UID, NULL );
- if ( p && *p ) /* yes */
- action = selected? 0 : -1;
- else /* no */
- action = selected? 1 : 0;
-
- if (action) {
- int rc = update_keysig_packet (&newsig, sig,
- main_pk, uid,
- sk,
- change_primary_uid_cb,
- action > 0? "x":NULL );
- if( rc ) {
- log_error ("update_keysig_packet failed: %s\n",
- g10_errstr(rc));
- 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;
- }
- }
- }
- }
- }
-
- free_secret_key( sk );
- return modified;
-}
-
-
-/*
- * Set preferences to new values for the selected user IDs
- */
-static int
-menu_set_preferences (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;
-
- 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,
- sk,
- keygen_upd_std_prefs,
- NULL );
- if( rc ) {
- log_error ("update_keysig_packet failed: %s\n",
- g10_errstr(rc));
- 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;
- }
- }
- }
- }
-
- free_secret_key( sk );
- return modified;
-}
-
-
-/****************
- * Select one user id or remove all selection if index is 0.
- * Returns: True if the selection changed;
- */
-static int
-menu_select_uid( KBNODE keyblock, int idx )
-{
- KBNODE node;
- int i;
-
- /* first check that the index is valid */
- if( idx ) {
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- if( ++i == idx )
- break;
- }
- }
- if( !node ) {
- tty_printf(_("No user ID with index %d\n"), idx );
- return 0;
- }
- }
- else { /* reset all */
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID )
- node->flag &= ~NODFLG_SELUID;
- }
- return 1;
- }
- /* and toggle the new index */
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_USER_ID ) {
- if( ++i == idx ) {
- if( (node->flag & NODFLG_SELUID) )
- node->flag &= ~NODFLG_SELUID;
- else
- node->flag |= NODFLG_SELUID;
- }
- }
- }
-
- return 1;
-}
-
-/****************
- * Select secondary keys
- * Returns: True if the selection changed;
- */
-static int
-menu_select_key( KBNODE keyblock, int idx )
-{
- KBNODE node;
- int i;
-
- /* first check that the index is valid */
- if( idx ) {
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- if( ++i == idx )
- break;
- }
- }
- if( !node ) {
- tty_printf(_("No secondary key with index %d\n"), idx );
- return 0;
- }
- }
- else { /* reset all */
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY )
- node->flag &= ~NODFLG_SELKEY;
- }
- return 1;
- }
- /* and set the new index */
- for( i=0, node = keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
- if( ++i == idx ) {
- if( (node->flag & NODFLG_SELKEY) )
- node->flag &= ~NODFLG_SELKEY;
- else
- node->flag |= NODFLG_SELKEY;
- }
- }
- }
-
- return 1;
-}
-
-
-static int
-count_uids_with_flag( KBNODE keyblock, unsigned flag )
-{
- KBNODE node;
- int i=0;
-
- for( node = keyblock; node; node = node->next )
- if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
- i++;
- return i;
-}
-
-static int
-count_keys_with_flag( KBNODE keyblock, unsigned flag )
-{
- KBNODE node;
- int i=0;
-
- for( node = keyblock; node; node = node->next )
- if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- || node->pkt->pkttype == PKT_SECRET_SUBKEY)
- && (node->flag & flag) )
- i++;
- return i;
-}
-
-static int
-count_uids( KBNODE keyblock )
-{
- KBNODE node;
- int i=0;
-
- for( node = keyblock; node; node = node->next )
- if( node->pkt->pkttype == PKT_USER_ID )
- i++;
- return i;
-}
-
-
-/****************
- * Returns true if there is at least one selected user id
- */
-static int
-count_selected_uids( KBNODE keyblock )
-{
- return count_uids_with_flag( keyblock, NODFLG_SELUID);
-}
-
-static int
-count_selected_keys( KBNODE keyblock )
-{
- return count_keys_with_flag( keyblock, NODFLG_SELKEY);
-}
-
-/* returns how many real (i.e. not attribute) uids are unmarked */
-static int
-real_uids_left( KBNODE keyblock )
-{
- KBNODE node;
- int real=0;
-
- for(node=keyblock;node;node=node->next)
- if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) &&
- !node->pkt->pkt.user_id->attrib_data)
- real++;
-
- return real;
-}
-
-/*
- * Ask whether the signature should be revoked. If the user commits this,
- * flag bit MARK_A is set on the signature and the user ID.
- */
-static void
-ask_revoke_sig( KBNODE keyblock, KBNODE node )
-{
- int doit=0;
- PKT_signature *sig = node->pkt->pkt.signature;
- KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
-
- if( !unode ) {
- log_error("Oops: no user ID for signature\n");
- return;
- }
-
- tty_printf(_("user ID: \""));
- tty_print_utf8_string( unode->pkt->pkt.user_id->name,
- unode->pkt->pkt.user_id->len );
-
- if(sig->flags.exportable)
- tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
- (ulong)sig->keyid[1], datestr_from_sig(sig) );
- else
- tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"),
- (ulong)sig->keyid[1], datestr_from_sig(sig) );
-
- if(sig->flags.expired)
- {
- tty_printf(_("This signature expired on %s.\n"),
- expirestr_from_sig(sig));
- /* Use a different question so we can have different help text */
- doit=cpr_get_answer_is_yes("ask_revoke_sig.expired",
- _("Are you sure you still want to revoke it? (y/N) "));
- }
- else
- doit=cpr_get_answer_is_yes("ask_revoke_sig.one",
- _("Create a revocation certificate for this signature? (y/N) "));
-
- if(doit) {
- node->flag |= NODFLG_MARK_A;
- unode->flag |= NODFLG_MARK_A;
- }
-}
-
-/****************
- * Display all user ids of the current public key together with signatures
- * done by one of our keys. Then walk over all this sigs and ask the user
- * whether he wants to revoke this signature.
- * Return: True when the keyblock has changed.
- */
-static int
-menu_revsig( KBNODE keyblock )
-{
- PKT_signature *sig;
- PKT_public_key *primary_pk;
- KBNODE node;
- int changed = 0;
- int rc, any, skip=1, all=!count_selected_uids(keyblock);
- struct revocation_reason_info *reason = NULL;
-
- /* FIXME: detect duplicates here */
- tty_printf(_("You have signed these user IDs:\n"));
- for( node = keyblock; node; node = node->next ) {
- node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
- if( node->pkt->pkttype == PKT_USER_ID ) {
- if( node->flag&NODFLG_SELUID || all ) {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- /* Hmmm: Should we show only UIDs with a signature? */
- tty_printf(" ");
- tty_print_utf8_string( uid->name, uid->len );
- tty_printf("\n");
- skip=0;
- }
- else
- skip=1;
- }
- else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
- && ((sig = node->pkt->pkt.signature),
- !seckey_available(sig->keyid) ) ) {
- if( (sig->sig_class&~3) == 0x10 ) {
- tty_printf(_(" signed by %08lX at %s%s%s\n"),
- (ulong)sig->keyid[1], datestr_from_sig(sig),
- sig->flags.exportable?"":" (non-exportable)",
- sig->flags.revocable?"":" (non-revocable)");
- if(sig->flags.revocable)
- node->flag |= NODFLG_SELSIG;
- }
- else if( sig->sig_class == 0x30 ) {
- tty_printf(_(" revoked by %08lX at %s\n"),
- (ulong)sig->keyid[1], datestr_from_sig(sig) );
- }
- }
- }
-
- /* ask */
- for( node = keyblock; node; node = node->next ) {
- if( !(node->flag & NODFLG_SELSIG) )
- continue;
- ask_revoke_sig( keyblock, node );
- }
-
- /* present selected */
- any = 0;
- for( node = keyblock; node; node = node->next ) {
- if( !(node->flag & NODFLG_MARK_A) )
- continue;
- if( !any ) {
- any = 1;
- tty_printf(_("You are about to revoke these signatures:\n"));
- }
- if( node->pkt->pkttype == PKT_USER_ID ) {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- tty_printf(" ");
- tty_print_utf8_string( uid->name, uid->len );
- tty_printf("\n");
- }
- else if( node->pkt->pkttype == PKT_SIGNATURE ) {
- sig = node->pkt->pkt.signature;
- tty_printf(_(" signed by %08lX at %s%s\n"),
- (ulong)sig->keyid[1], datestr_from_sig(sig),
- sig->flags.exportable?"":_(" (non-exportable)") );
- }
- }
- if( !any )
- return 0; /* none selected */
-
- if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
- _("Really create the revocation certificates? (y/N) ")) )
- return 0; /* forget it */
-
- reason = ask_revocation_reason( 0, 1, 0 );
- if( !reason ) { /* user decided to cancel */
- return 0;
- }
-
- /* now we can sign the user ids */
- reloop: /* (must use this, because we are modifing the list) */
- primary_pk = keyblock->pkt->pkt.public_key;
- for( node=keyblock; node; node = node->next ) {
- KBNODE unode;
- PACKET *pkt;
- struct sign_attrib attrib;
- PKT_secret_key *sk;
-
- if( !(node->flag & NODFLG_MARK_A)
- || node->pkt->pkttype != PKT_SIGNATURE )
- continue;
- unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
- assert( unode ); /* we already checked this */
-
- memset( &attrib, 0, sizeof attrib );
- attrib.reason = reason;
- attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
-
- node->flag &= ~NODFLG_MARK_A;
- sk = m_alloc_secure_clear( sizeof *sk );
- if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
- log_info(_("no secret key\n"));
- continue;
- }
- rc = make_keysig_packet( &sig, primary_pk,
- unode->pkt->pkt.user_id,
- NULL,
- sk,
- 0x30, 0, 0, 0, 0,
- sign_mk_attrib,
- &attrib );
- free_secret_key(sk);
- if( rc ) {
- log_error(_("signing failed: %s\n"), g10_errstr(rc));
- release_revocation_reason_info( reason );
- return changed;
- }
- changed = 1; /* we changed the keyblock */
- update_trust = 1;
- /* Are we revoking our own uid? */
- if(primary_pk->keyid[0]==sig->keyid[0] &&
- primary_pk->keyid[1]==sig->keyid[1])
- unode->pkt->pkt.user_id->is_revoked=1;
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = sig;
- insert_kbnode( unode, new_kbnode(pkt), 0 );
- goto reloop;
- }
-
- release_revocation_reason_info( reason );
- return changed;
-}
-
-/****************
- * Revoke some of the secondary keys.
- * Hmmm: Should we add a revocation to the secret keyring too?
- * Does its all make sense to duplicate most of the information?
- */
-static int
-menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
-{
- PKT_public_key *mainpk;
- KBNODE node;
- int changed = 0;
- int rc;
- struct revocation_reason_info *reason = NULL;
-
- reason = ask_revocation_reason( 1, 0, 0 );
- if( !reason ) { /* user decided to cancel */
- return 0;
- }
-
-
- reloop: /* (better this way because we are modifing the keyring) */
- mainpk = pub_keyblock->pkt->pkt.public_key;
- for( node = pub_keyblock; node; node = node->next ) {
- if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
- && (node->flag & NODFLG_SELKEY) ) {
- PACKET *pkt;
- PKT_signature *sig;
- PKT_secret_key *sk;
- PKT_public_key *subpk = node->pkt->pkt.public_key;
- struct sign_attrib attrib;
-
- memset( &attrib, 0, sizeof attrib );
- attrib.reason = reason;
-
- node->flag &= ~NODFLG_SELKEY;
- sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
- rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk,
- 0x28, 0, 0, 0, 0,
- sign_mk_attrib, &attrib );
- free_secret_key(sk);
- if( rc ) {
- log_error(_("signing failed: %s\n"), g10_errstr(rc));
- release_revocation_reason_info( reason );
- return changed;
- }
- changed = 1; /* we changed the keyblock */
-
- pkt = m_alloc_clear( sizeof *pkt );
- pkt->pkttype = PKT_SIGNATURE;
- pkt->pkt.signature = sig;
- insert_kbnode( node, new_kbnode(pkt), 0 );
- goto reloop;
- }
- }
- commit_kbnode( &pub_keyblock );
- /*commit_kbnode( &sec_keyblock );*/
-
- /* No need to set update_trust here since signing keys no longer
- are used to certify other keys, so there is no change in trust
- when revoking/removing them */
-
- release_revocation_reason_info( reason );
- return changed;
-}
-
-
-static int
-enable_disable_key( KBNODE keyblock, int disable )
-{
- PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
- ->pkt->pkt.public_key;
- unsigned int trust, newtrust;
-
- trust = newtrust = get_ownertrust (pk);
- newtrust &= ~TRUST_FLAG_DISABLED;
- if( disable )
- newtrust |= TRUST_FLAG_DISABLED;
- if( trust == newtrust )
- return 0; /* already in that state */
- update_ownertrust(pk, newtrust );
- return 0;
-}
-
-
-static void
-menu_showphoto( KBNODE keyblock )
-{
- KBNODE node;
- int select_all = !count_selected_uids(keyblock);
- int count=0;
- PKT_public_key *pk=NULL;
- u32 keyid[2];
-
- /* Look for the public key first. We have to be really, really,
- explicit as to which photo this is, and what key it is a UID on
- since people may want to sign it. */
-
- for( node = keyblock; node; node = node->next )
- {
- if( node->pkt->pkttype == PKT_PUBLIC_KEY )
- {
- pk = node->pkt->pkt.public_key;
- keyid_from_pk(pk, keyid);
- }
- else if( node->pkt->pkttype == PKT_USER_ID )
- {
- PKT_user_id *uid = node->pkt->pkt.user_id;
- count++;
-
- if((select_all || (node->flag & NODFLG_SELUID)) &&
- uid->attribs!=NULL)
- {
- int i;
-
- for(i=0;i<uid->numattribs;i++)
- {
- byte type;
- u32 size;
-
- if(uid->attribs[i].type==ATTRIB_IMAGE &&
- parse_image_header(&uid->attribs[i],&type,&size))
- {
- tty_printf(_("Displaying %s photo ID of size %ld for "
- "key 0x%08lX (uid %d)\n"),
- image_type_to_string(type,1),
- (ulong)size,(ulong)keyid[1],count);
- show_photos(&uid->attribs[i],1,pk,NULL);
- }
- }
- }
- }
- }
-}