* trustdb.h, trustdb.c (clean_uids_from_key): New. Walk through the
authorDavid Shaw <dshaw@jabberwocky.com>
Mon, 30 May 2005 03:43:30 +0000 (03:43 +0000)
committerDavid Shaw <dshaw@jabberwocky.com>
Mon, 30 May 2005 03:43:30 +0000 (03:43 +0000)
user IDs on a key, and mark any that aren't valid for deletion.

* keyedit.c (menu_clean_uids_from_key): New function to call
clean_uids_from_key() on a key.  (keyedit_menu): Call it from here as
part of the "clean" command.

g10/ChangeLog
g10/keyedit.c
g10/trustdb.c
g10/trustdb.h

index 87608c3..2250bc9 100644 (file)
@@ -1,3 +1,13 @@
+2005-05-29  David Shaw  <dshaw@jabberwocky.com>
+
+       * trustdb.h, trustdb.c (clean_uids_from_key): New.  Walk through
+       the user IDs on a key, and mark any that aren't valid for
+       deletion.
+
+       * keyedit.c (menu_clean_uids_from_key): New function to call
+       clean_uids_from_key() on a key.
+       (keyedit_menu): Call it from here as part of the "clean" command.
+
 2005-05-26  David Shaw  <dshaw@jabberwocky.com>
 
        * g10.c (main): Default {export|import}-unusable-sigs to off until
index cc7ff72..d85c888 100644 (file)
@@ -53,7 +53,8 @@ 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 int menu_clean_uids(KBNODE keyblock);
+static int menu_clean_sigs_from_uids(KBNODE keyblock);
+static int menu_clean_uids_from_key(KBNODE keyblock);
 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
 static int menu_addrevoker( KBNODE pub_keyblock,
                            KBNODE sec_keyblock, int sensitive );
@@ -2138,17 +2139,25 @@ keyedit_menu( const char *username, STRLIST locusr,
            {
              if(*arg_string)
                {
-                 if(ascii_strcasecmp(arg_string,"sigs")!=0
-                    && ascii_strcasecmp(arg_string,"signatures")!=0
-                    && ascii_strcasecmp(arg_string,"certs")!=0
-                    && ascii_strcasecmp(arg_string,"certificates")!=0)
+                 if(ascii_strcasecmp(arg_string,"sigs")==0
+                    || ascii_strcasecmp(arg_string,"signatures")==0
+                    || ascii_strcasecmp(arg_string,"certs")==0
+                    || ascii_strcasecmp(arg_string,"certificates")==0)
+                   modified=menu_clean_sigs_from_uids(keyblock);
+                 else if(ascii_strcasecmp(arg_string,"uids")==0)
+                   redisplay=modified=menu_clean_uids_from_key(keyblock);
+                 else if(ascii_strcasecmp(arg_string,"all")==0)
                    {
-                     tty_printf(_("Unable to clean `%s'\n"),arg_string);
-                     break;
+                     modified=menu_clean_sigs_from_uids(keyblock);
+                     modified+=menu_clean_uids_from_key(keyblock);
+                     redisplay=modified;
                    }
+                 else
+                   tty_printf(_("Unable to clean `%s'\n"),arg_string);
                }
-
-             modified=menu_clean_uids(keyblock);
+             else
+               tty_printf(_("Please specify item to clean: `sigs',"
+                            " `uids', or `all'\n"));
            }
            break;
 
@@ -2699,7 +2708,8 @@ show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
     i = 0;
     for( node = keyblock; node; node = node->next )
       {
-       if( node->pkt->pkttype == PKT_USER_ID )
+       if( node->pkt->pkttype == PKT_USER_ID
+           && !is_deleted_kbnode(node))
          {
            PKT_user_id *uid = node->pkt->pkt.user_id;
            ++i;
@@ -3134,7 +3144,7 @@ menu_delsig( KBNODE pub_keyblock )
 }
 
 static int
-menu_clean_uids(KBNODE keyblock)
+menu_clean_sigs_from_uids(KBNODE keyblock)
 {
   KBNODE uidnode;
   int modified=0;
@@ -3149,7 +3159,7 @@ menu_clean_uids(KBNODE keyblock)
          char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
                                    uidnode->pkt->pkt.user_id->len,
                                    0);
-         deleted=clean_uid(keyblock,uidnode,opt.verbose);
+         deleted=clean_sigs_from_uid(keyblock,uidnode,opt.verbose);
          if(deleted)
            {
              tty_printf(deleted==1?
@@ -3168,6 +3178,42 @@ menu_clean_uids(KBNODE keyblock)
   return modified;
 }
 
+static int
+menu_clean_uids_from_key(KBNODE keyblock)
+{
+  KBNODE node;
+  int modified;
+
+  modified=clean_uids_from_key(keyblock,opt.verbose);
+
+  if(modified)
+    {
+      for(node=keyblock->next;node;node=node->next)
+       {
+         if(node->pkt->pkttype==PKT_USER_ID && is_deleted_kbnode(node))
+           {
+             char *reason;
+             char *user=utf8_to_native(node->pkt->pkt.user_id->name,
+                                       node->pkt->pkt.user_id->len,0);
+
+             if(node->pkt->pkt.user_id->is_revoked)
+               reason=_("revoked");
+             else if(node->pkt->pkt.user_id->is_expired)
+               reason=_("expired");
+             else
+               reason=_("invalid");
+
+             tty_printf(_("User ID \"%s\" removed: %s\n"),user,reason);
+
+             m_free(user);
+           }
+       }
+    }
+  else
+    tty_printf(_("No user IDs are removable.\n"));
+
+  return modified;
+}
 
 /****************
  * Remove some of the secondary keys
index 751f1b4..f690557 100644 (file)
@@ -1574,7 +1574,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
 }
 
 int
-clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy)
+clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy)
 {
   int deleted=0;
   KBNODE node;
@@ -1635,6 +1635,79 @@ clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy)
   return deleted;
 }
 
+/* This is substantially easier than clean_sigs_from_uid since we just
+   have to establish if the uid has a valid self-sig, is not revoked,
+   and is not expired.  Note that this does not take into account
+   whether the uid has a trust path to it - just whether the keyholder
+   themselves has certified the uid.  Returns how many user IDs were
+   removed. */
+int
+clean_uids_from_key(KBNODE keyblock,int noisy)
+{
+  int uidcount=0,delete_until_next,deleted=0;
+  KBNODE node;
+
+  assert(keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
+
+  merge_keys_and_selfsig(keyblock);
+
+  /* First count how many user IDs we have.  We need to be careful
+     that we don't delete them all as some keys could actually have NO
+     valid user IDs.  2440 requires at least 1 user ID packet, valid
+     or not. */
+  for(node=keyblock->next;
+      node && node->pkt->pkttype!=PKT_PUBLIC_SUBKEY;
+      node=node->next)
+    if(node->pkt->pkttype==PKT_USER_ID)
+      uidcount++;
+
+  for(node=keyblock->next;
+      node && node->pkt->pkttype!=PKT_PUBLIC_SUBKEY && uidcount>deleted+1;
+      node=node->next)
+    {
+      if(node->pkt->pkttype==PKT_USER_ID)
+       {
+         /* Skip valid user IDs, and non-self-signed user IDs if
+            --allow-non-selfsigned-uid is set. */
+         if(node->pkt->pkt.user_id->created
+            || (!node->pkt->pkt.user_id->is_expired
+                && !node->pkt->pkt.user_id->is_revoked
+                && opt.allow_non_selfsigned_uid))
+           delete_until_next=0;
+         else
+           {
+             delete_until_next=1;
+             deleted++;
+
+             if(noisy)
+               {
+                 char *reason;
+                 char *user=utf8_to_native(node->pkt->pkt.user_id->name,
+                                           node->pkt->pkt.user_id->len,0);
+
+                 if(node->pkt->pkt.user_id->is_revoked)
+                   reason=_("revoked");
+                 else if(node->pkt->pkt.user_id->is_expired)
+                   reason=_("expired");
+                 else
+                   reason=_("invalid");
+
+                 log_info("removing user ID \"%s\" from key %s: %s\n",
+                          user,keystr(keyblock->pkt->pkt.public_key->keyid),
+                          reason);
+
+                 m_free(user);
+               }
+           }
+       }
+
+      if(delete_until_next)
+       delete_kbnode(node);
+    }
+    
+  return deleted;
+}
+
 /* Used by validate_one_keyblock to confirm a regexp within a trust
    signature.  Returns 1 for match, and 0 for no match or regex
    error. */
index a9f98c7..b914063 100644 (file)
@@ -81,7 +81,8 @@ const char *get_ownertrust_string (PKT_public_key *pk);
 void update_ownertrust (PKT_public_key *pk, unsigned int new_trust );
 int clear_ownertrusts (PKT_public_key *pk);
 
-int clean_uid(KBNODE keyblock,KBNODE uidnode,int noisy);
+int clean_sigs_from_uid(KBNODE keyblock,KBNODE uidnode,int noisy);
+int clean_uids_from_key(KBNODE keyblock,int noisy);
 
 /*-- tdbdump.c --*/
 void list_trustdb(const char *username);