See ChangeLog: Tue Aug 31 17:20:44 CEST 1999 Werner Koch
[gnupg.git] / g10 / keyedit.c
index 85f3dfa..d54e90d 100644 (file)
@@ -47,6 +47,7 @@ static void show_key_and_fingerprint( KBNODE keyblock );
 static void show_fingerprint( PKT_public_key *pk );
 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
 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_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_select_uid( KBNODE keyblock, int idx );
@@ -58,6 +59,7 @@ static int count_selected_uids( 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 );
 
 #define CONTROL_D ('D' - 'A' + 1)
 
@@ -104,6 +106,68 @@ get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
 
 
 /****************
+ * Print information about a signature, chek 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;
+
+    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:
+       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       %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( *is_selfsig ) {
+           tty_printf( is_rev? _("[revocation]")
+                             : _("[self-signature]") );
+       }
+       else {
+           size_t n;
+           char *p = get_user_id( sig->keyid, &n );
+           tty_print_utf8_string( p, n > 40? 40 : n );
+           m_free(p);
+       }
+       tty_printf("\n");
+    }
+    return (sigrc == '!');
+}
+
+
+
+/****************
  * Check the keysigs and set the flags to indicate errors.
  * Returns true if error found.
  */
@@ -112,7 +176,6 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
 {
     KBNODE kbctx;
     KBNODE node;
-    int rc;
     int inv_sigs = 0;
     int no_key = 0;
     int oth_err = 0;
@@ -129,7 +192,7 @@ check_all_keysigs( KBNODE keyblock, int only_selected )
                selected = (node->flag & NODFLG_SELUID);
            if( selected ) {
                tty_printf("uid  ");
-               tty_print_string( uid->name, uid->len );
+               tty_print_utf8_string( uid->name, uid->len );
                tty_printf("\n");
                if( anyuid && !has_selfsig )
                    mis_selfsig++;
@@ -140,54 +203,14 @@ 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 == 0x30 )  ) {
-           PKT_signature *sig = node->pkt->pkt.signature;
-           int sigrc, selfsig;
-           int is_rev = sig->sig_class == 0x30;
+           int selfsig;
 
-           switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
-             case 0:
-               node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
-               sigrc = '!';
-               break;
-             case G10ERR_BAD_SIGN:
-               node->flag = NODFLG_BADSIG;
-               sigrc = '-';
-               inv_sigs++;
-               break;
-             case G10ERR_NO_PUBKEY:
-               node->flag = NODFLG_NOKEY;
-               sigrc = '?';
-               no_key++;
-               break;
-             default:
-               node->flag = NODFLG_SIGERR;
-               sigrc = '%';
-               oth_err++;
-               break;
-           }
-           if( sigrc != '?' ) {
-               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( is_rev? _("[revocation]")
-                                     : _("[self-signature]") );
-                   if( sigrc == '!' )
-                       has_selfsig = 1;
-               }
-               else {
-                   size_t n;
-                   char *p = get_user_id( sig->keyid, &n );
-                   tty_print_string( p, n > 40? 40 : n );
-                   m_free(p);
-               }
-               tty_printf("\n");
-               /* fixme: Should we update the trustdb here */
+           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 )
@@ -307,7 +330,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
             "Are you really sure that you want to sign this key\n"
             "with your key: \""));
        p = get_user_id( sk_keyid, &n );
-       tty_print_string( p, n );
+       tty_print_utf8_string( p, n );
        m_free(p); p = NULL;
        tty_printf("\"\n\n");
 
@@ -428,7 +451,7 @@ change_passphrase( KBNODE keyblock )
        for(;;) {
            s2k->mode = opt.s2k_mode;
            s2k->hash_algo = opt.s2k_digest_algo;
-           dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
+           dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 );
            if( !dek ) {
                tty_printf(_("passphrase not correctly repeated; try again.\n"));
            }
@@ -474,7 +497,9 @@ change_passphrase( KBNODE keyblock )
 /****************
  * 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 fixed.
+ * 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 )
@@ -513,57 +538,64 @@ fix_keyblock( KBNODE keyblock )
 }
 
 /****************
- * Menu driven key editor
+ * 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 )
+keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
+                                                   int sign_mode )
 {
     enum cmdids { cmdNONE = 0,
           cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
-          cmdLSIGN, cmdREVSIG, cmdREVKEY,
+          cmdLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG,
           cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
           cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
-          cmdNOP };
+          cmdENABLEKEY, cmdDISABLEKEY,
+          cmdINVCMD, cmdNOP };
     static struct { const char *name;
                    enum cmdids id;
                    int need_sk;
+                   int signmode;
                    const char *desc;
                  } cmds[] = {
-       { N_("quit")    , cmdQUIT   , 0, N_("quit this menu") },
-       { N_("q")       , cmdQUIT   , 0, NULL   },
-       { N_("save")    , cmdSAVE   , 0, N_("save and quit") },
-       { N_("help")    , cmdHELP   , 0, N_("show this help") },
-       {    "?"        , cmdHELP   , 0, NULL   },
-       { N_("fpr")     , cmdFPR    , 0, N_("show fingerprint") },
-       { N_("list")    , cmdLIST   , 0, N_("list key and user ids") },
-       { N_("l")       , cmdLIST   , 0, NULL   },
-       { N_("uid")     , cmdSELUID , 0, N_("select user id N") },
-       { N_("key")     , cmdSELKEY , 0, N_("select secondary key N") },
-       { N_("check")   , cmdCHECK  , 0, N_("list signatures") },
-       { N_("c")       , cmdCHECK  , 0, NULL },
-       { N_("sign")    , cmdSIGN   , 0, N_("sign the key") },
-       { N_("s")       , cmdSIGN   , 0, NULL },
-       { N_("lsign")   , cmdLSIGN  , 0, N_("sign the key locally") },
-       { N_("debug")   , cmdDEBUG  , 0, NULL },
-       { N_("adduid")  , cmdADDUID , 1, N_("add a user id") },
-       { N_("deluid")  , cmdDELUID , 0, N_("delete user id") },
-       { N_("addkey")  , cmdADDKEY , 1, N_("add a secondary key") },
-       { N_("delkey")  , cmdDELKEY , 0, N_("delete a secondary key") },
-       { N_("expire")  , cmdEXPIRE , 1, N_("change the expire date") },
-       { N_("toggle")  , cmdTOGGLE , 1, N_("toggle between secret "
-                                           "and public key listing") },
-       { N_("t"     )  , cmdTOGGLE , 1, NULL },
-       { 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") },
-       { N_("revkey")  , cmdREVKEY , 1, N_("revoke a secondary key") },
+       { N_("quit")    , cmdQUIT      , 0,1, N_("quit this menu") },
+       { N_("q")       , cmdQUIT      , 0,1, NULL   },
+       { N_("save")    , cmdSAVE      , 0,1, N_("save and quit") },
+       { N_("help")    , cmdHELP      , 0,1, N_("show this help") },
+       {    "?"        , cmdHELP      , 0,1, NULL   },
+       { N_("fpr")     , cmdFPR       , 0,1, N_("show fingerprint") },
+       { N_("list")    , cmdLIST      , 0,1, N_("list key and user ids") },
+       { N_("l")       , cmdLIST      , 0,1, NULL   },
+       { N_("uid")     , cmdSELUID    , 0,1, N_("select user id N") },
+       { N_("key")     , cmdSELKEY    , 0,0, N_("select secondary key N") },
+       { N_("check")   , cmdCHECK     , 0,1, N_("list signatures") },
+       { N_("c")       , cmdCHECK     , 0,1, NULL },
+       { N_("sign")    , cmdSIGN      , 0,1, N_("sign the key") },
+       { N_("s")       , cmdSIGN      , 0,1, NULL },
+       { N_("lsign")   , cmdLSIGN     , 0,1, N_("sign the key locally") },
+       { N_("debug")   , cmdDEBUG     , 0,0, NULL },
+       { N_("adduid")  , cmdADDUID    , 1,0, N_("add a user id") },
+       { N_("deluid")  , cmdDELUID    , 0,0, N_("delete user id") },
+       { N_("addkey")  , cmdADDKEY    , 1,0, N_("add a secondary key") },
+       { N_("delkey")  , cmdDELKEY    , 0,0, N_("delete a secondary key") },
+       { N_("delsig")  , cmdDELSIG    , 0,0, N_("delete signatures") },
+       { N_("expire")  , cmdEXPIRE    , 1,0, N_("change the expire date") },
+       { N_("toggle")  , cmdTOGGLE    , 1,0, N_("toggle between secret "
+                                                "and public key listing") },
+       { N_("t"     )  , cmdTOGGLE    , 1,0, NULL },
+       { N_("pref")    , cmdPREF      , 0,0,  N_("list preferences") },
+       { N_("passwd")  , cmdPASSWD    , 1,0, N_("change the passphrase") },
+       { N_("trust")   , cmdTRUST     , 0,0,  N_("change the ownertrust") },
+       { N_("revsig")  , cmdREVSIG    , 0,0, N_("revoke signatures") },
+       { N_("revkey")  , cmdREVKEY    , 1,0, N_("revoke a secondary key") },
+       { N_("disable") , cmdDISABLEKEY, 0,0, N_("disable a key") },
+       { N_("enable")  , cmdENABLEKEY , 0,0, N_("enable a key") },
 
     { NULL, cmdNONE } };
-    enum cmdids cmd;
+    enum cmdids cmd = 0;
     int rc = 0;
     KBNODE keyblock = NULL;
     KBPOS keyblockpos;
@@ -583,18 +615,27 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
        goto leave;
     }
 
-    /* first try to locate it as secret key */
-    rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
-    if( !rc ) {
-       rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
-       if( rc ) {
-           log_error("%s: secret keyblock read problem: %s\n",
-                                           username, g10_errstr(rc));
-           goto leave;
+    if( sign_mode ) {
+       commands = NULL;
+       append_to_strlist( &commands, sign_mode == 1? "sign":"lsign" );
+       have_commands = 1;
+    }
+
+
+    if( !sign_mode ) {
+       /* first try to locate it as secret key */
+       rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
+       if( !rc ) {
+           rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
+           if( rc ) {
+               log_error("%s: secret keyblock read problem: %s\n",
+                                               username, g10_errstr(rc));
+               goto leave;
+           }
+           merge_keys_and_selfsig( sec_keyblock );
+           if( fix_keyblock( sec_keyblock ) )
+               sec_modified++;
        }
-       merge_keys_and_selfsig( sec_keyblock );
-       if( fix_keyblock( sec_keyblock ) )
-           sec_modified++;
     }
 
     /* and now get the public key */
@@ -603,9 +644,11 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
        goto leave;
     if( fix_keyblock( keyblock ) )
        modified++;
+    if( collapse_uids( &keyblock ) )
+       modified++;
 
     if( sec_keyblock ) { /* check that they match */
-       /* FIXME: check that they both match */
+       /* fixme: check that they both match */
        tty_printf(_("Secret key is available.\n"));
     }
 
@@ -635,13 +678,13 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
                    have_commands = 0;
            }
            if( !have_commands ) {
-               answer = cpr_get("keyedit.cmd", _("Command> "));
+               answer = cpr_get("", _("Command> "));
                cpr_kill_prompt();
            }
            trim_spaces(answer);
        } while( *answer == '#' );
 
-       arg_number = 0;
+       arg_number = 0; /* Yes, here is the init which egcc complains about*/
        if( !*answer )
            cmd = cmdLIST;
        else if( *answer == CONTROL_D )
@@ -658,10 +701,13 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
                arg_number = atoi(p);
            }
 
-           for(i=0; cmds[i].name; i++ )
+           for(i=0; cmds[i].name; i++ ) {
                if( !stricmp( answer, cmds[i].name ) )
                    break;
-           if( cmds[i].need_sk && !sec_keyblock ) {
+           }
+           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;
            }
@@ -671,53 +717,15 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
        switch( cmd )  {
          case cmdHELP:
            for(i=0; cmds[i].name; i++ ) {
-               if( cmds[i].need_sk && !sec_keyblock )
+               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 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:
-           if( modified || sec_modified  ) {
-               if( modified ) {
-                   rc = update_keyblock( &keyblockpos, keyblock );
-                   if( rc ) {
-                       log_error(_("update failed: %s\n"), g10_errstr(rc) );
-                       break;
-                   }
-               }
-               if( sec_modified ) {
-                   rc = update_keyblock( &sec_keyblockpos, 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"));
-           rc = update_trust_record( keyblock, 0, NULL );
-           if( rc )
-               log_error(_("update of trustdb failed: %s\n"),
-                           g10_errstr(rc) );
-           goto leave;
-
          case cmdLIST:
            redisplay = 1;
            break;
@@ -752,7 +760,9 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
                    break;
                }
            }
-           sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN );
+           if( !sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN )
+               && sign_mode )
+               goto do_cmd_save;
            break;
 
          case cmdDEBUG:
@@ -801,6 +811,19 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
            }
            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;
@@ -892,6 +915,61 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
            }
            break;
 
+         case cmdENABLEKEY:
+         case cmdDISABLEKEY:
+           if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) {
+               redisplay = 1;
+               modified = 1;
+           }
+           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 = update_keyblock( &keyblockpos, keyblock );
+                   if( rc ) {
+                       log_error(_("update failed: %s\n"), g10_errstr(rc) );
+                       break;
+                   }
+               }
+               if( sec_modified ) {
+                   rc = update_keyblock( &sec_keyblockpos, 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"));
+           /* TODO: we should keep track whether we have changed
+            *       something relevant to the trustdb */
+           if( !modified && sign_mode )
+               rc = 0; /* we can skip at least in this case */
+           else
+               rc = update_trust_record( keyblock, 0, NULL );
+           if( rc )
+               log_error(_("update of trustdb failed: %s\n"),
+                           g10_errstr(rc) );
+           goto leave;
+
+         case cmdINVCMD:
          default:
            tty_printf("\n");
            tty_printf(_("Invalid command  (try \"help\")\n"));
@@ -981,6 +1059,12 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
                          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->local_id )&TRUST_FLAG_DISABLED)) {
+                   tty_printf("\n*** ");
+                   tty_printf(_("This key has been disabled"));
+               }
+
                if( with_fpr  ) {
                    tty_printf("\n");
                    show_fingerprint( pk );
@@ -1028,7 +1112,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked,
                   tty_printf("(%d)* ", i);
                else
                   tty_printf("(%d)  ", i);
-               tty_print_string( uid->name, uid->len );
+               tty_print_utf8_string( uid->name, uid->len );
                tty_printf("\n");
                if( with_prefs )
                    show_prefs( keyblock, uid );
@@ -1054,7 +1138,7 @@ show_key_and_fingerprint( KBNODE keyblock )
        }
        else if( node->pkt->pkttype == PKT_USER_ID ) {
            PKT_user_id *uid = node->pkt->pkt.user_id;
-           tty_print_string( uid->name, uid->len );
+           tty_print_utf8_string( uid->name, uid->len );
            break;
        }
     }
@@ -1223,6 +1307,70 @@ menu_deluid( KBNODE pub_keyblock, 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)"));
+          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
  */
@@ -1296,9 +1444,9 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
        return 0;
     }
     else if( n1 )
-       tty_printf(_("Changing exiration time for a secondary key.\n"));
+       tty_printf(_("Changing expiration time for a secondary key.\n"));
     else {
-       tty_printf(_("Changing exiration time for the primary key.\n"));
+       tty_printf(_("Changing expiration time for the primary key.\n"));
        mainkey=1;
     }
 
@@ -1560,8 +1708,8 @@ ask_revoke_sig( KBNODE keyblock, KBNODE node )
     }
 
     tty_printf(_("user ID: \""));
-    tty_print_string( unode->pkt->pkt.user_id->name,
-                     unode->pkt->pkt.user_id->len );
+    tty_print_utf8_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) );
 
@@ -1596,7 +1744,7 @@ menu_revsig( KBNODE keyblock )
            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_print_utf8_string( uid->name, uid->len );
            tty_printf("\n");
        }
        else if( node->pkt->pkttype == PKT_SIGNATURE
@@ -1633,7 +1781,7 @@ menu_revsig( KBNODE keyblock )
        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_print_utf8_string( uid->name, uid->len );
            tty_printf("\n");
        }
        else if( node->pkt->pkttype == PKT_SIGNATURE ) {
@@ -1753,3 +1901,23 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
 }
 
 
+static int
+enable_disable_key( KBNODE keyblock, int disable )
+{
+    ulong lid = find_kbnode( keyblock, PKT_PUBLIC_KEY )
+                           ->pkt->pkt.public_key->local_id;
+    unsigned int trust, newtrust;
+
+    /* Note: Because the keys have beed displayed, we have
+     * ensured that local_id has been set */
+    trust = newtrust = get_ownertrust( lid );
+    newtrust &= ~TRUST_FLAG_DISABLED;
+    if( disable )
+       newtrust |= TRUST_FLAG_DISABLED;
+    if( trust == newtrust )
+       return 0; /* already in that state */
+    if( !update_ownertrust( lid, newtrust ) )
+       return 1;
+    return 0;
+}
+