* build-packet.c (build_sig_subpkt): Comments.
[gnupg.git] / g10 / keyedit.c
index 7f298c0..333552c 100644 (file)
@@ -1,5 +1,6 @@
 /* keyedit.c - keyedit stuff
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ *               2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -63,6 +64,7 @@ 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_revuid( KBNODE keyblock, KBNODE sec_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 );
@@ -85,6 +87,8 @@ static int update_trust=0;
 struct sign_attrib {
     int non_exportable,non_revocable;
     struct revocation_reason_info *reason;
+    byte trust_depth,trust_value;
+    char *trust_regexp;
 };
 
 /****************
@@ -100,6 +104,9 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
     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);
@@ -126,7 +133,7 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
        break;
     }
     if( sigrc != '?' || print_without_key ) {
-        tty_printf("%s%c%c %c%c%c%c%c %08lX %s   ",
+        tty_printf("%s%c%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:' ',
@@ -135,6 +142,8 @@ print_and_check_one_sig( KBNODE keyblock, KBNODE node,
                   sig->flags.policy_url?'P':' ',
                   sig->flags.notation?'N':' ',
                    sig->flags.expired?'X':' ',
+                  (sig->trust_depth>9)?'T':
+                  (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
                   (ulong)sig->keyid[1], datestr_from_sig(sig));
        if( sigrc == '%' )
            tty_printf("[%s] ", g10_errstr(rc) );
@@ -255,10 +264,126 @@ sign_mk_attrib( PKT_signature *sig, void *opaque )
     if( attrib->reason )
        revocation_reason_build_cb( sig, attrib->reason );
 
+    if(attrib->trust_depth)
+      {
+       /* Not critical.  If someone doesn't understand trust sigs,
+          this can still be a valid regular signature. */
+        buf[0] = attrib->trust_depth;
+       buf[1] = attrib->trust_value;
+       build_sig_subpkt(sig,SIGSUBPKT_TRUST,buf,2);
+
+       /* Critical.  If someone doesn't understands regexps, this
+          whole sig should be invalid.  Note the +1 for the length -
+          regexps are null terminated. */
+       if(attrib->trust_regexp)
+         build_sig_subpkt(sig,SIGSUBPKT_FLAG_CRITICAL|SIGSUBPKT_REGEXP,
+                          attrib->trust_regexp,
+                          strlen(attrib->trust_regexp)+1);
+      }
+
     return 0;
 }
 
+static void
+trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
+{
+  char *p;
+
+  *trust_value=0;
+  *trust_depth=0;
+  *regexp=NULL;
+
+  tty_printf("\n");
+  /* Same string as pkclist.c:do_edit_ownertrust */
+  tty_printf(_(
+              "Please decide how far you trust this user to correctly\n"
+              "verify other users' keys (by looking at passports,\n"
+              "checking fingerprints from different sources...)?\n\n"));
+  tty_printf (_("   (%d) I trust marginally\n"), 1);
+  tty_printf (_("   (%d) I trust fully\n"), 2);
+  tty_printf("\n");
+
+  while(*trust_value==0)
+    {
+      p = cpr_get("trustsig_prompt.trust_value",_("Your selection? "));
+      trim_spaces(p);
+      cpr_kill_prompt();
+      /* 60 and 120 are as per RFC2440 */
+      if(p[0]=='1' && !p[1])
+       *trust_value=60;
+      else if(p[0]=='2' && !p[1])
+       *trust_value=120;
+      m_free(p);
+    }
+
+  tty_printf("\n");
+
+  tty_printf(_(
+             "Please enter the depth of this trust signature.\n"
+             "A depth greater than 1 allows the key you are signing to make\n"
+             "trust signatures on your behalf.\n"));
+  tty_printf("\n");
+
+  while(*trust_depth==0)
+    {
+      p = cpr_get("trustsig_prompt.trust_depth",_("Your selection? "));
+      trim_spaces(p);
+      cpr_kill_prompt();
+      *trust_depth=atoi(p);
+      m_free(p);
+      if(*trust_depth<1 || *trust_depth>255)
+       *trust_depth=0;
+    }
+
+  tty_printf("\n");
+
+  tty_printf(_("Please enter a domain to restrict this signature, "
+              "or enter for none.\n"));
+
+  tty_printf("\n");
+
+  p=cpr_get("trustsig_prompt.trust_regexp",_("Your selection? "));
+  trim_spaces(p);
+  cpr_kill_prompt();
+
+  if(strlen(p)>0)
+    {
+      char *q=p;
+      int regexplen=100,ind;
+
+      *regexp=m_alloc(regexplen);
+
+      /* Now mangle the domain the user entered into a regexp.  To do
+        this, \-escape everything that isn't alphanumeric, and attach
+        "<[^>]+[@.]" to the front, and ">$" to the end. */
+
+      strcpy(*regexp,"<[^>]+[@.]");
+      ind=strlen(*regexp);
+
+      while(*q)
+       {
+         if(!((*q>='A' && *q<='Z')
+              || (*q>='a' && *q<='z') || (*q>='0' && *q<='9')))
+           (*regexp)[ind++]='\\';
+
+         (*regexp)[ind++]=*q;
+
+         if((regexplen-ind)<3)
+           {
+             regexplen+=100;
+             *regexp=m_realloc(*regexp,regexplen);
+           }
+
+         q++;
+       }
+
+      (*regexp)[ind]='\0';
+      strcat(*regexp,">$");
+    }
 
+  m_free(p);
+  tty_printf("\n");
+}
 
 /****************
  * Loop over all locusr and and sign the uids after asking.
@@ -267,7 +392,7 @@ sign_mk_attrib( PKT_signature *sig, void *opaque )
  */
 static int
 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
-          int local , int nonrevocable )
+          int local, int nonrevocable, int trust )
 {
     int rc = 0;
     SK_LIST sk_list = NULL;
@@ -303,11 +428,12 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
         u32 sk_keyid[2],pk_keyid[2];
        size_t n;
-       char *p;
+       char *p,*trust_regexp=NULL;
        int force_v4=0,class=0,selfsig=0;
        u32 duration=0,timestamp=0;
+       byte trust_depth=0,trust_value=0;
 
-       if(local || nonrevocable ||
+       if(local || nonrevocable || trust ||
           opt.cert_policy_url || opt.cert_notation_data)
          force_v4=1;
 
@@ -374,7 +500,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                      }
                    else if(!uidnode->pkt->pkt.user_id->created)
                      {
-                       tty_printf(_("Warning: user ID \"%s\" is not "
+                       tty_printf(_("WARNING: user ID \"%s\" is not "
                                     "self-signed.\n"),user);
                      }
 
@@ -408,10 +534,35 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                            {
                              force_v4=1;
                              node->flag|=NODFLG_DELSIG;
+                             m_free(user);
                              continue;
                            }
                      }
 
+                   /* Is the current signature expired? */
+                   if(node->pkt->pkt.signature->flags.expired)
+                     {
+                       tty_printf(_("Your current signature on \"%s\"\n"
+                                    "has expired.\n"),user);
+
+                       if(cpr_get_answer_is_yes("sign_uid.replace_expired_okay",
+                                                _("Do you want to issue a "
+                                                  "new signature to replace "
+                                                  "the expired one? (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;
+                           m_free(user);
+                           continue;
+                         }
+                     }
+
                    if(!node->pkt->pkt.signature->flags.exportable && !local)
                      {
                        /* It's a local sig, and we want to make a
@@ -432,6 +583,7 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                                in place. */
 
                            node->flag|=NODFLG_DELSIG;
+                           m_free(user);
                            continue;
                          }
                      }
@@ -446,6 +598,18 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                       tty_printf(_(
                          "\"%s\" was already signed by key %08lX\n"),
                                  user,(ulong)sk_keyid[1] );
+
+                   if(opt.expert
+                      && cpr_get_answer_is_yes("sign_uid.dupe_okay",
+                                               _("Do you want to sign it "
+                                                 "again anyway? (y/N) ")))
+                     {
+                       /* Don't delete the old sig here since this is
+                          an --expert thing. */
+                       m_free(user);
+                       continue;
+                     }
+
                     sprintf (buf, "%08lX%08lX",
                              (ulong)sk->keyid[0], (ulong)sk->keyid[1] );
                     write_status_text (STATUS_ALREADY_SIGNED, buf);
@@ -548,45 +712,52 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
 
        if(selfsig)
          ;
-       else if(opt.batch)
-         class=0x10+opt.def_cert_check_level;
        else
          {
-           char *answer;
+           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");
+               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"));
+               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);
+                   m_free(answer);
+                 }
              }
+
+           if(trust)
+             trustsig_prompt(&trust_value,&trust_depth,&trust_regexp);
          }
 
        tty_printf(_("Are you really sure that you want to sign this key\n"
@@ -602,12 +773,12 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
 
            if( local )
              tty_printf(
-                        _("\nWarning: the signature will not be marked "
+                        _("\nWARNING: the signature will not be marked "
                           "as non-exportable.\n"));
 
            if( nonrevocable )
              tty_printf(
-                        _("\nWarning: the signature will not be marked "
+                        _("\nWARNING: the signature will not be marked "
                           "as non-revocable.\n"));
          }
        else
@@ -659,6 +830,9 @@ sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
                memset( &attrib, 0, sizeof attrib );
                attrib.non_exportable = local;
                attrib.non_revocable = nonrevocable;
+               attrib.trust_depth = trust_depth;
+               attrib.trust_value = trust_value;
+               attrib.trust_regexp = trust_regexp;
                node->flag &= ~NODFLG_MARK_A;
 
                 /* we force creation of a v4 signature for local
@@ -779,10 +953,10 @@ change_passphrase( KBNODE keyblock )
            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);
+                                     s2k, 2, errtext, NULL);
            if( !dek ) {
-               errtext = _("passphrase not correctly repeated; try again");
-               tty_printf ("%s.\n", errtext);
+               errtext = N_("passphrase not correctly repeated; try again");
+               tty_printf ("%s.\n", _(errtext));
            }
            else if( !dek->keylen ) {
                rc = 0;
@@ -882,12 +1056,12 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
 {
     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 };
+           cmdTSIGN, cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY,
+          cmdREVUID, 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;
@@ -909,6 +1083,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
        { 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_("tsign")   , cmdTSIGN     , 0,1,1, N_("make a trust signature")},
        { 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") },
@@ -934,6 +1109,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
        { 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_("revuid")  , cmdREVUID    , 1,1,0, N_("revoke a user ID") },
        { 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") },
@@ -970,13 +1146,14 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
     }
 
     /* get the public key */
-    rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd);
+    rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1);
     if( rc )
        goto leave;
     if( fix_keyblock( keyblock ) )
        modified++;
     if( collapse_uids( &keyblock ) )
        modified++;
+    reorder_keyblock(keyblock);
 
     if( !sign_mode ) {/* see whether we have a matching secret key */
         PKT_public_key *pk = keyblock->pkt->pkt.public_key;
@@ -1126,6 +1303,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
          case cmdLSIGN: /* sign (only the public key) */
          case cmdNRSIGN: /* sign (only the public key) */
          case cmdNRLSIGN: /* sign (only the public key) */
+         case cmdTSIGN:
            if( pk->is_revoked )
              {
                tty_printf(_("Key is revoked."));
@@ -1154,7 +1332,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
            }
            if( !sign_uids( keyblock, locusr, &modified,
                            (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN),
-                           (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN))
+                           (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN),
+                           (cmd == cmdTSIGN))
                && sign_mode )
                goto do_cmd_save;
            break;
@@ -1270,6 +1449,25 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
            }
            break;
 
+         case cmdREVUID: {
+               int n1;
+
+               if( !(n1=count_selected_uids(keyblock)) )
+                   tty_printf(_("You must select at least one user ID.\n"));
+               else if( cpr_get_answer_is_yes(
+                           "keyedit.revoke.uid.okay",
+                       n1 > 1? _("Really revoke all selected user IDs? ")
+                             : _("Really revoke this user ID? ")
+                      ) ) {
+                 if(menu_revuid(keyblock,sec_keyblock))
+                   {
+                     modified=1;
+                     redisplay=1;
+                   }
+               }
+           }
+           break;
+
          case cmdREVKEY: {
                int n1;
 
@@ -1342,9 +1540,10 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
 
          case cmdUPDPREF: 
             {
-                p = keygen_get_std_prefs ();
-                tty_printf (("Current preference list: %s\n"), p);
-                m_free (p);
+             PKT_user_id *temp=keygen_get_std_prefs();
+             tty_printf(_("Current preference list:\n"));
+             show_prefs(temp,1);
+             m_free(temp);
             }
             if (cpr_get_answer_is_yes ("keyedit.updpref.okay",
                                         count_selected_uids (keyblock)?
@@ -1463,7 +1662,8 @@ show_prefs (PKT_user_id *uid, int verbose)
 
     if (verbose) {
         int any, des_seen=0, sha1_seen=0, uncomp_seen=0;
-        tty_printf ("     Cipher: ");
+        tty_printf ("     ");
+       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);
@@ -1485,7 +1685,8 @@ show_prefs (PKT_user_id *uid, int verbose)
                 tty_printf (", ");
             tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES));
         }
-        tty_printf ("\n     Hash: ");
+        tty_printf ("\n     ");
+       tty_printf (_("Digest: "));
         for(i=any=0; prefs[i].type; i++ ) {
             if( prefs[i].type == PREFTYPE_HASH ) {
                 const char *s = digest_algo_to_string (prefs[i].value);
@@ -1507,7 +1708,8 @@ show_prefs (PKT_user_id *uid, int verbose)
                 tty_printf (", ");
             tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1));
         }
-        tty_printf ("\n     Compression: ");
+        tty_printf ("\n     ");
+       tty_printf (_("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);
@@ -1533,9 +1735,23 @@ show_prefs (PKT_user_id *uid, int verbose)
            }
            tty_printf ("%s",compress_algo_to_string(0));
         }
-        tty_printf ("\n     Features: ");
-       if(uid->mdc_feature)
-         tty_printf ("MDC");
+       if(uid->mdc_feature || !uid->ks_modify)
+         {
+           tty_printf ("\n     ");
+           tty_printf (_("Features: "));
+           any=0;
+           if(uid->mdc_feature)
+             {
+               tty_printf ("MDC");
+               any=1;
+             }
+           if(!uid->ks_modify)
+             {
+               if(any)
+                 tty_printf (", ");
+               tty_printf (_("Keyserver no-modify"));
+             }
+         }
        tty_printf("\n");
     }
     else {
@@ -1548,6 +1764,8 @@ show_prefs (PKT_user_id *uid, int verbose)
         }
         if (uid->mdc_feature)
             tty_printf (" [mdc]");
+        if (!uid->ks_modify)
+            tty_printf (" [no-ks-modify]");
         tty_printf("\n");
     }
 }
@@ -1560,8 +1778,9 @@ static void
 show_key_with_all_names_colon (KBNODE keyblock)
 {
   KBNODE node;
-  int i, j;
+  int i, j, ulti_hack=0;
   byte pk_version=0;
+  PKT_public_key *primary=NULL;
 
   /* the keys */
   for ( node = keyblock; node; node = node->next )
@@ -1570,14 +1789,12 @@ show_key_with_all_names_colon (KBNODE keyblock)
           || (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;
+             primary=pk;
            }
 
           keyid_from_pk (pk, keyid);
@@ -1589,8 +1806,14 @@ show_key_with_all_names_colon (KBNODE keyblock)
             putchar ('r');
           else if (pk->has_expired)
             putchar ('e');
-          else 
-            putchar (trust);
+          else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks ))
+           {
+             int trust = get_validity_info (pk, NULL);
+             if(trust=='u')
+               ulti_hack=1;
+             putchar (trust);
+           }
+
           printf (":%u:%d:%08lX%08lX:%lu:%lu:",
                   nbits_from_pk (pk),
                   pk->pubkey_algo,
@@ -1600,7 +1823,9 @@ show_key_with_all_names_colon (KBNODE keyblock)
           if (pk->local_id)
             printf ("%lu", pk->local_id);
           putchar (':');
-          putchar (otrust);
+          if (node->pkt->pkttype==PKT_PUBLIC_KEY
+             && !(opt.fast_list_mode || opt.no_expensive_trust_checks ))
+           putchar(get_ownertrust_info (pk));
           putchar(':');
           putchar('\n');
           
@@ -1633,19 +1858,36 @@ show_key_with_all_names_colon (KBNODE keyblock)
        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);
-             }
+             printf("uat:");
+           else
+             printf("uid:");
+
+           if ( uid->is_revoked )
+             printf("r::::::::");
+           else if ( uid->is_expired )
+             printf("e::::::::");
+           else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
+             printf("::::::::");
            else
              {
-               printf ("uid:%c::::::::", trustletter);
-               print_string (stdout, uid->name, uid->len, ':');
+               int uid_validity;
+
+               if( primary && !ulti_hack )
+                 uid_validity = get_validity_info( primary, uid );
+               else
+                 uid_validity = 'u';
+               printf("%c::::::::",uid_validity);
              }
+
+           if(uid->attrib_data)
+             printf ("%u %lu",uid->numattribs,uid->attrib_len);
+           else
+             print_string (stdout, uid->name, uid->len, ':');
+
             putchar (':');
             /* signature class */
             putchar (':');
@@ -1667,6 +1909,8 @@ show_key_with_all_names_colon (KBNODE keyblock)
                   } 
                 if (uid->mdc_feature)
                   printf (",mdc");
+                if (!uid->ks_modify)
+                  printf (",no-ks-modify");
               } 
             putchar (':');
             /* flags */
@@ -1712,15 +1956,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
        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;
+           const char *otrust="err",*trust="err";
 
            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);
+                trust = get_validity_string (pk, NULL);
+               otrust = get_ownertrust_string (pk);
 
                 /* Show a warning once */
                 if (!did_warn
@@ -1739,13 +1983,15 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                     for(i=0;i<pk->numrevkeys;i++) {
                         u32 r_keyid[2];
                         char *user;
-           
+                       const char *algo=
+                         pubkey_algo_to_string(pk->revkey[i].algid);
+
                         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));
+                                   algo?algo:"?");
                         tty_print_utf8_string (user, strlen (user));
                         if ((pk->revkey[i].class&0x40))
                           tty_printf (_(" (sensitive)"));
@@ -1762,20 +2008,28 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                          (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 );
+           tty_printf("\n");
+
+           if( node->pkt->pkttype == PKT_PUBLIC_KEY )
+             {
+               tty_printf("                     ");
+               tty_printf(_("trust: %-13s"), otrust);
+               tty_printf(_("validity: %s"), trust );
+               tty_printf("\n");
                if( node->pkt->pkttype == PKT_PUBLIC_KEY
-                   && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) {
-                   tty_printf("\n*** ");
+                   && (get_ownertrust (pk)&TRUST_FLAG_DISABLED))
+                 {
+                   tty_printf("*** ");
                    tty_printf(_("This key has been disabled"));
-               }
-
-               if( with_fpr  ) {
                    tty_printf("\n");
-                   print_fingerprint ( pk, NULL, 2 );
-               }
-           }
-           tty_printf("\n");
+                 }
+             }
+
+           if( node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr )
+             {
+               print_fingerprint ( pk, NULL, 2 );
+               tty_printf("\n");
+             }
        }
        else if( node->pkt->pkttype == PKT_SECRET_KEY
            || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
@@ -1821,9 +2075,9 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                else
                   tty_printf("(%d)  ", i);
                 if ( uid->is_revoked )
-                    tty_printf ("[revoked] ");
+                    tty_printf (_("[revoked] "));
                 if ( uid->is_expired )
-                    tty_printf ("[expired] ");
+                    tty_printf (_("[expired] "));
                tty_print_utf8_string( uid->name, uid->len );
                tty_printf("\n");
                if( with_prefs )
@@ -1832,7 +2086,7 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
                      show_prefs (uid, with_prefs == 2);
                    else
                      tty_printf(_("There are no preferences on a "
-                                  "PGP 2.x-style key.\n"));
+                                  "PGP 2.x-style user ID.\n"));
                  }
            }
        }
@@ -1845,6 +2099,74 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
 
 }
 
+
+/* 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 )
 {
@@ -1854,7 +2176,7 @@ show_key_and_fingerprint( KBNODE keyblock )
     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 ",
+           tty_printf("pub   %4u%c/%08lX %s ",
                          nbits_from_pk( pk ),
                          pubkey_letter( pk->pubkey_algo ),
                          (ulong)keyid_from_pk(pk,NULL),
@@ -1921,8 +2243,9 @@ menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
 
       /* 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.  Don't bother to ask this if the key already has a
-         photo - any damage has already been done at that point. -dms */
+         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)
@@ -2164,9 +2487,9 @@ menu_delkey( KBNODE pub_keyblock, KBNODE sec_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 */
+    /* No need to set update_trust here since signing keys are no
+       longer used to certify other keys, so there is no change in
+       trust when revoking/removing them */
 }
 
 
@@ -2190,6 +2513,33 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
   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(;;)
@@ -2211,7 +2561,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
       if(answer[0]=='\0' || answer[0]=='\004')
        goto fail;
 
-      rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL);
+      rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
 
       if(rc)
        {
@@ -2227,6 +2577,11 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
          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
@@ -2234,12 +2589,44 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
             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   ",
+      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) );
@@ -2251,25 +2638,24 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
       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(_("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): "))
+                               _("Are you sure you want to appoint this "
+                                 "key as a designated revoker? (y/N): ")))
        continue;
 
-      revkey.class=0x80;
-      if(sensitive)
-       revkey.class|=0x40;
-      revkey.algid=revoker_pk->pubkey_algo;
       free_public_key(revoker_pk);
+      revoker_pk=NULL;
       break;
     }
 
-  rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 0, 0, 0,
+  /* 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 )
     {
@@ -2391,15 +2777,12 @@ menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
                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 );
+                 rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL,
+                                           sk, keygen_add_key_expire, 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 );
+                 rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk,
+                                           sk, keygen_add_key_expire, sub_pk );
                if( rc ) {
                    log_error("make_keysig_packet failed: %s\n",
                                                    g10_errstr(rc));
@@ -2544,7 +2927,7 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
 
                 if (action) {
                     int rc = update_keysig_packet (&newsig, sig,
-                                               main_pk, uid, 
+                                              main_pk, uid, NULL,
                                                sk,
                                                change_primary_uid_cb,
                                                action > 0? "x":NULL );
@@ -2629,7 +3012,7 @@ menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
                 int rc;
 
                 rc = update_keysig_packet (&newsig, sig,
-                                           main_pk, uid, 
+                                           main_pk, uid, NULL,
                                            sk,
                                            keygen_upd_std_prefs,
                                            NULL );
@@ -2878,7 +3261,7 @@ menu_revsig( KBNODE keyblock )
     PKT_public_key *primary_pk;
     KBNODE node;
     int changed = 0;
-    int rc, any;
+    int rc, any, skip=1, all=!count_selected_uids(keyblock);
     struct revocation_reason_info *reason = NULL;
 
     /* FIXME: detect duplicates here  */
@@ -2886,13 +3269,18 @@ menu_revsig( KBNODE keyblock )
     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_utf8_string( uid->name, uid->len );
-           tty_printf("\n");
+           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( node->pkt->pkttype == PKT_SIGNATURE
+       else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
                && ((sig = node->pkt->pkt.signature),
                      !seckey_available(sig->keyid)  ) ) {
            if( (sig->sig_class&~3) == 0x10 ) {
@@ -2991,7 +3379,10 @@ menu_revsig( KBNODE keyblock )
        }
        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;
@@ -3003,6 +3394,109 @@ menu_revsig( KBNODE keyblock )
     return changed;
 }
 
+/* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
+   keyblock changed. */
+static int
+menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
+{
+  PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
+  PKT_secret_key *sk = copy_secret_key( NULL,
+                                       sec_keyblock->pkt->pkt.secret_key );
+  KBNODE node;
+  int changed = 0;
+  int rc;
+  struct revocation_reason_info *reason = NULL;
+
+  /* Note that this is correct as per the RFCs, but nevertheless
+     somewhat meaningless in the real world.  1991 did define the 0x30
+     sig class, but PGP 2.x did not actually implement it, so it would
+     probably be safe to use v4 revocations everywhere. -ds */
+
+  for( node = pub_keyblock; node; node = node->next )
+    if(pk->version>3 || (node->pkt->pkttype==PKT_USER_ID &&
+                        node->pkt->pkt.user_id->selfsigversion>3))
+      {
+       if((reason = ask_revocation_reason( 0, 1, 4 )))
+         break;
+       else
+         goto leave;
+      }
+
+ reloop: /* (better this way because we are modifing the keyring) */
+  for( node = pub_keyblock; node; node = node->next )
+    if(node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
+      {
+       PKT_user_id *uid=node->pkt->pkt.user_id;
+
+       if(uid->is_revoked)
+         {
+           char *user=utf8_to_native(uid->name,uid->len,0);
+           log_info(_("user ID \"%s\" is already revoked\n"),user);
+           m_free(user);
+         }
+       else
+         {
+           PACKET *pkt;
+           PKT_signature *sig;
+           struct sign_attrib attrib;
+           u32 timestamp=make_timestamp();
+
+           if(uid->created>=timestamp)
+             {
+               /* Okay, this is a problem.  The user ID selfsig was
+                  created in the future, so we need to warn the user and
+                  set our revocation timestamp one second after that so
+                  everything comes out clean. */
+
+               log_info(_("WARNING: a user ID signature is dated %d"
+                          " seconds in the future\n"),uid->created-timestamp);
+
+               timestamp=uid->created+1;
+             }
+
+           memset( &attrib, 0, sizeof attrib );
+           attrib.reason = reason;
+
+           node->flag &= ~NODFLG_SELUID;
+
+           rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x30, 0,
+                                    (reason==NULL)?3:0, timestamp, 0,
+                                    sign_mk_attrib, &attrib );
+           if( rc )
+             {
+               log_error(_("signing failed: %s\n"), g10_errstr(rc));
+               goto leave;
+             }
+           else
+             {
+               pkt = m_alloc_clear( sizeof *pkt );
+               pkt->pkttype = PKT_SIGNATURE;
+               pkt->pkt.signature = sig;
+               insert_kbnode( node, new_kbnode(pkt), 0 );
+
+               /* If the trustdb has an entry for this key+uid then the
+                  trustdb needs an update. */
+               if(!update_trust
+                  && (get_validity(pk,uid)&TRUST_MASK)>=TRUST_UNDEFINED)
+                 update_trust=1;
+
+               changed = 1;
+               node->pkt->pkt.user_id->is_revoked=1;
+
+               goto reloop;
+             }
+         }
+      }
+
+  if(changed)
+    commit_kbnode( &pub_keyblock );
+
+ leave:
+  free_secret_key(sk);
+  release_revocation_reason_info( reason );
+  return changed;
+}
+
 /****************
  * Revoke some of the secondary keys.
  * Hmmm: Should we add a revocation to the secret keyring too?
@@ -3022,7 +3516,6 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
        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 ) {
@@ -3068,7 +3561,10 @@ menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
     return changed;
 }
 
-
+/* Note that update_ownertrust is going to mark the trustdb dirty when
+   enabling or disabling a key.  This is arguably sub-optimal as
+   disabled keys are still counted in the web of trust, but perhaps
+   not worth adding extra complexity to change. -ds */
 static int
 enable_disable_key( KBNODE keyblock, int disable )
 {