aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keyedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keyedit.c')
-rw-r--r--g10/keyedit.c184
1 files changed, 179 insertions, 5 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 7ae006a68..1ba92a2cd 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1,5 +1,5 @@
/* keyedit.c - keyedit stuff
- * Copyright (C) 1998 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -56,6 +56,7 @@ 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 count_selected_keys( KBNODE keyblock );
+static int menu_revsig( KBNODE keyblock );
#define CONTROL_D ('D' - 'A' + 1)
@@ -67,6 +68,7 @@ static int count_selected_keys( KBNODE keyblock );
#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_uid_attrib {
@@ -119,6 +121,8 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
int anyuid = 0;
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
+ int is_rev = 0;
+
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = node->pkt->pkt.user_id;
@@ -135,7 +139,8 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
}
}
else if( selected && node->pkt->pkttype == PKT_SIGNATURE
- && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
+ && (node->pkt->pkt.signature->sig_class&~3) == 0x10
+ && (is_rev = node->pkt->pkt.signature->sig_class == 0x30) ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc, selfsig;
@@ -161,14 +166,16 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
break;
}
if( sigrc != '?' ) {
- tty_printf("sig%c %08lX %s ",
+ tty_printf("%s%c %08lX %s ",
+ is_rev? "rev":"sig",
sigrc, sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
tty_printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
;
else if( selfsig ) {
- tty_printf( _("[self-signature]") );
+ tty_printf( is_rev? _("[revocation]")
+ : _("[self-signature]") );
if( sigrc == '!' )
has_selfsig = 1;
}
@@ -278,6 +285,8 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
&& (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] ) {
+ /* Fixme: see whether there is a revocation in which
+ * case we should allow to sign it again. */
tty_printf(_("Already signed by key %08lX\n"),
(ulong)sk_keyid[1] );
uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
@@ -514,7 +523,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
{
enum cmdids { cmdNONE = 0,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
- cmdLSIGN,
+ cmdLSIGN, cmdREVSIG,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
cmdNOP };
@@ -550,6 +559,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
{ N_("pref") , cmdPREF , 0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0, N_("change the ownertrust") },
+ { N_("revsig") , cmdREVSIG , 0, N_("revoke signatures") },
{ NULL, cmdNONE } };
enum cmdids cmd;
@@ -852,6 +862,13 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
case cmdNOP:
break;
+ case cmdREVSIG:
+ if( menu_revsig( keyblock ) ) {
+ redisplay = 1;
+ modified = 1;
+ }
+ break;
+
default:
tty_printf("\n");
tty_printf(_("Invalid command (try \"help\")\n"));
@@ -1490,3 +1507,160 @@ count_selected_keys( KBNODE keyblock )
return count_keys_with_flag( keyblock, NODFLG_SELKEY);
}
+/*
+ * 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 )
+{
+ 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_string( unode->pkt->pkt.user_id->name,
+ unode->pkt->pkt.user_id->len );
+ tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
+ sig->keyid[1], datestr_from_sig(sig) );
+
+ if( cpr_get_answer_is_yes("ask_revoke_sig.one",
+ _("Create a revocation certificate for this signature? (y/N)")) ) {
+ 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 upd_trust = 0;
+ int rc, any;
+
+ /* 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 ) {
+ PKT_user_id *uid = node->pkt->pkt.user_id;
+ /* Hmmm: Should we show only UIDs with a signature? */
+ tty_printf(" ");
+ tty_print_string( uid->name, uid->len );
+ tty_printf("\n");
+ }
+ else if( 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\n",
+ sig->keyid[1], datestr_from_sig(sig) );
+ node->flag |= NODFLG_SELSIG;
+ }
+ else if( sig->sig_class == 0x30 ) {
+ tty_printf(" revoked by %08lX at %s\n",
+ 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_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\n",
+ sig->keyid[1], datestr_from_sig(sig) );
+ }
+ }
+ 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 */
+
+
+ /* 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_uid_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 );
+ 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,
+ sign_uid_mk_attrib,
+ &attrib );
+ free_secret_key(sk);
+ if( rc ) {
+ log_error(_("signing failed: %s\n"), g10_errstr(rc));
+ return changed;
+ }
+ changed = 1; /* we changed the keyblock */
+ upd_trust = 1;
+
+ pkt = m_alloc_clear( sizeof *pkt );
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = sig;
+ insert_kbnode( unode, new_kbnode(pkt), PKT_SIGNATURE );
+ goto reloop;
+ }
+
+ if( upd_trust )
+ clear_trust_checked_flag( primary_pk );
+
+ return changed;
+}
+
+