gpg: Add debug helper to --edit-keys's check sub-command.
[gnupg.git] / g10 / keyedit.c
index c5f02f7..8d87a01 100644 (file)
@@ -1,7 +1,6 @@
-/* keyedit.c - keyedit stuff
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- *               2008, 2009, 2010 Free Software Foundation, Inc.
- * Copyright (C) 2013, 2014 Werner Koch
+/* keyedit.c - Edit properties of a key
+ * Copyright (C) 1998-2010 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2015 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -31,7 +30,6 @@
 # include <readline/readline.h>
 #endif
 
-#define JNLIB_NEED_LOG_LOGV
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
@@ -53,13 +51,16 @@ static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
                        int verbose);
 static void show_names (estream_t fp, KBNODE keyblock, PKT_public_key * pk,
                        unsigned int flag, int with_prefs);
-static void show_key_with_all_names (estream_t fp,
+static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                                      KBNODE keyblock, int only_marked,
                                     int with_revoker, int with_fpr,
                                     int with_subkeys, int with_prefs,
                                      int nowarn);
-static void show_key_and_fingerprint (KBNODE keyblock);
-static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name);
+static void show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys);
+static void show_key_and_grip (kbnode_t keyblock);
+static void subkey_expire_warning (kbnode_t keyblock);
+static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name,
+                        const char *uidstr);
 static void menu_deluid (KBNODE pub_keyblock);
 static int menu_delsig (KBNODE pub_keyblock);
 static int menu_clean (KBNODE keyblock, int self_only);
@@ -127,20 +128,21 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
   /* 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)))
+  rc = check_key_signature (keyblock, node, is_selfsig);
+  switch (gpg_err_code (rc))
     {
     case 0:
       node->flag &= ~(NODFLG_BADSIG | NODFLG_NOKEY | NODFLG_SIGERR);
       sigrc = '!';
       break;
-    case G10ERR_BAD_SIGN:
+    case GPG_ERR_BAD_SIGNATURE:
       node->flag = NODFLG_BADSIG;
       sigrc = '-';
       if (inv_sigs)
        ++ * inv_sigs;
       break;
-    case G10ERR_NO_PUBKEY:
-    case G10ERR_UNU_PUBKEY:
+    case GPG_ERR_NO_PUBKEY:
+    case GPG_ERR_UNUSABLE_PUBKEY:
       node->flag = NODFLG_NOKEY;
       sigrc = '?';
       if (no_key)
@@ -156,23 +158,23 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
 
   if (sigrc != '?' || print_without_key)
     {
-      printf ("sig:%c::%d:%08lX%08lX:%lu:%lu:",
-             sigrc, sig->pubkey_algo, (ulong) sig->keyid[0],
-             (ulong) sig->keyid[1], (ulong) sig->timestamp,
-             (ulong) sig->expiredate);
+      es_printf ("sig:%c::%d:%08lX%08lX:%lu:%lu:",
+                 sigrc, sig->pubkey_algo, (ulong) sig->keyid[0],
+                 (ulong) sig->keyid[1], (ulong) sig->timestamp,
+                 (ulong) sig->expiredate);
 
       if (sig->trust_depth || sig->trust_value)
-       printf ("%d %d", sig->trust_depth, sig->trust_value);
+       es_printf ("%d %d", sig->trust_depth, sig->trust_value);
 
-      printf (":");
+      es_printf (":");
 
       if (sig->trust_regexp)
        es_write_sanitized (es_stdout,
                            sig->trust_regexp, strlen (sig->trust_regexp),
                            ":", NULL);
 
-      printf ("::%02x%c\n", sig->sig_class,
-             sig->flags.exportable ? 'x' : 'l');
+      es_printf ("::%02x%c\n", sig->sig_class,
+                 sig->flags.exportable ? 'x' : 'l');
 
       if (opt.show_subpackets)
        print_subpackets_colon (sig);
@@ -183,13 +185,15 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
 
 
 /*
- * Print information about a signature, check it and return true
- * if the signature is okay. NODE must be a signature packet.
+ * Print information about a signature, check it and return true if
+ * the signature is okay.  NODE must be a signature packet.  With
+ * EXTENDED set all possible signature list options will always be
+ * printed.
  */
 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)
+                        int *is_selfsig, int print_without_key, int extended)
 {
   PKT_signature *sig = node->pkt->pkt.signature;
   int rc, sigrc;
@@ -198,20 +202,21 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
   /* 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)))
+  rc = check_key_signature (keyblock, node, is_selfsig);
+  switch (gpg_err_code (rc))
     {
     case 0:
       node->flag &= ~(NODFLG_BADSIG | NODFLG_NOKEY | NODFLG_SIGERR);
       sigrc = '!';
       break;
-    case G10ERR_BAD_SIGN:
+    case GPG_ERR_BAD_SIGNATURE:
       node->flag = NODFLG_BADSIG;
       sigrc = '-';
       if (inv_sigs)
        ++ * inv_sigs;
       break;
-    case G10ERR_NO_PUBKEY:
-    case G10ERR_UNU_PUBKEY:
+    case GPG_ERR_NO_PUBKEY:
+    case GPG_ERR_UNUSABLE_PUBKEY:
       node->flag = NODFLG_NOKEY;
       sigrc = '?';
       if (no_key)
@@ -238,18 +243,21 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
                  sig->flags.expired ? 'X' : ' ',
                  (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
                                                  0) ? '0' +
-                 sig->trust_depth : ' ', keystr (sig->keyid),
+                 sig->trust_depth : ' ',
+                  keystr (sig->keyid),
                  datestr_from_sig (sig));
-      if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
+      if ((opt.list_options & LIST_SHOW_SIG_EXPIRE) || extended )
        tty_printf (" %s", expirestr_from_sig (sig));
       tty_printf ("  ");
       if (sigrc == '%')
-       tty_printf ("[%s] ", g10_errstr (rc));
+       tty_printf ("[%s] ", gpg_strerror (rc));
       else if (sigrc == '?')
        ;
       else if (*is_selfsig)
        {
          tty_printf (is_rev ? _("[revocation]") : _("[self-signature]"));
+          if (extended && sig->flags.chosen_selfsig)
+            tty_printf ("*");
        }
       else
        {
@@ -264,17 +272,20 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
        }
       tty_printf ("\n");
 
-      if (sig->flags.policy_url && (opt.list_options & LIST_SHOW_POLICY_URLS))
+      if (sig->flags.policy_url
+          && ((opt.list_options & LIST_SHOW_POLICY_URLS) || extended))
        show_policy_url (sig, 3, 0);
 
-      if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
+      if (sig->flags.notation
+          && ((opt.list_options & LIST_SHOW_NOTATIONS) || extended))
        show_notation (sig, 3, 0,
                       ((opt.
                         list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0) +
                       ((opt.
                         list_options & LIST_SHOW_USER_NOTATIONS) ? 2 : 0));
 
-      if (sig->flags.pref_ks && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
+      if (sig->flags.pref_ks
+          && ((opt.list_options & LIST_SHOW_KEYSERVER_URLS) || extended))
        show_keyserver_url (sig, 3, 0);
     }
 
@@ -288,7 +299,7 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
  * Returns true if error found.
  */
 static int
-check_all_keysigs (KBNODE keyblock, int only_selected)
+check_all_keysigs (KBNODE keyblock, int only_selected, int only_selfsigs)
 {
   KBNODE kbctx;
   KBNODE node;
@@ -299,10 +310,16 @@ check_all_keysigs (KBNODE keyblock, int only_selected)
   int mis_selfsig = 0;
   int selected = !only_selected;
   int anyuid = 0;
+  u32 keyid[2];
 
   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     {
-      if (node->pkt->pkttype == PKT_USER_ID)
+      if (node->pkt->pkttype == PKT_PUBLIC_KEY)
+        {
+          if (only_selfsigs)
+            keyid_from_pk (node->pkt->pkt.public_key, keyid);
+        }
+      else if (node->pkt->pkttype == PKT_USER_ID)
        {
          PKT_user_id *uid = node->pkt->pkt.user_id;
 
@@ -324,9 +341,14 @@ check_all_keysigs (KBNODE keyblock, int only_selected)
                   || node->pkt->pkt.signature->sig_class == 0x30))
        {
          int selfsig;
-
-         if (print_and_check_one_sig (keyblock, node, &inv_sigs,
-                                      &no_key, &oth_err, &selfsig, 0))
+          PKT_signature *sig = node->pkt->pkt.signature;
+
+          if (only_selfsigs
+              && !(keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]))
+            ;  /* Not a selfsig but we want only selfsigs - skip.  */
+         else if (print_and_check_one_sig (keyblock, node, &inv_sigs,
+                                            &no_key, &oth_err, &selfsig,
+                                            0, only_selfsigs))
            {
              if (selfsig)
                has_selfsig = 1;
@@ -506,7 +528,7 @@ trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
  * function won't ask the user and use sensible defaults.
  */
 static int
-sign_uids (estream_t fp,
+sign_uids (ctrl_t ctrl, estream_t fp,
            kbnode_t keyblock, strlist_t locusr, int *ret_modified,
           int local, int nonrevocable, int trust, int interactive,
            int quick)
@@ -518,19 +540,6 @@ sign_uids (estream_t fp,
   KBNODE node, uidnode;
   PKT_public_key *primary_pk = NULL;
   int select_all = !count_selected_uids (keyblock) || interactive;
-  int all_v3 = 1;
-
-  /* Are there any non-v3 sigs on this key already? */
-  if (PGP2)
-    {
-      for (node = keyblock; node; node = node->next)
-        if (node->pkt->pkttype == PKT_SIGNATURE &&
-            node->pkt->pkt.signature->version > 3)
-          {
-            all_v3 = 0;
-            break;
-          }
-    }
 
   /* Build a list of all signators.
    *
@@ -548,14 +557,10 @@ sign_uids (estream_t fp,
     {
       u32 sk_keyid[2], pk_keyid[2];
       char *p, *trust_regexp = NULL;
-      int force_v4 = 0, class = 0, selfsig = 0;
+      int class = 0, selfsig = 0;
       u32 duration = 0, timestamp = 0;
       byte trust_depth = 0, trust_value = 0;
 
-      if (local || nonrevocable || trust
-          || opt.cert_policy_url || opt.cert_notations)
-       force_v4 = 1;
-
       pk = sk_rover->pk;
       keyid_from_pk (pk, sk_keyid);
 
@@ -579,14 +584,7 @@ sign_uids (estream_t fp,
 
              /* Is this a self-sig? */
              if (pk_keyid[0] == sk_keyid[0] && pk_keyid[1] == sk_keyid[1])
-               {
-                 selfsig = 1;
-                 /* Do not force a v4 sig here, otherwise it would
-                    be difficult to remake a v3 selfsig.  If this
-                    is a v3->v4 promotion case, then we set
-                    force_v4 later anyway. */
-                 force_v4 = 0;
-               }
+                selfsig = 1;
            }
          else if (node->pkt->pkttype == PKT_USER_ID)
            {
@@ -728,7 +726,6 @@ sign_uids (estream_t fp,
                                                     "it to an OpenPGP self-"
                                                     "signature? (y/N) ")))
                          {
-                           force_v4 = 1;
                            node->flag |= NODFLG_DELSIG;
                            xfree (user);
                            continue;
@@ -827,7 +824,7 @@ sign_uids (estream_t fp,
 
       /* Ask whether we really should sign these user id(s). */
       tty_fprintf (fp, "\n");
-      show_key_with_all_names (fp, keyblock, 1, 0, 1, 0, 0, 0);
+      show_key_with_all_names (ctrl, fp, keyblock, 1, 0, 1, 0, 0, 0);
       tty_fprintf (fp, "\n");
 
       if (primary_pk->expiredate && !selfsig)
@@ -872,7 +869,6 @@ sign_uids (estream_t fp,
                         passphrase, etc). */
                      timestamp = now;
                      duration = primary_pk->expiredate - now;
-                     force_v4 = 1;
                    }
 
                  cpr_kill_prompt ();
@@ -891,32 +887,6 @@ sign_uids (estream_t fp,
            duration = parse_expire_string (opt.def_cert_expire);
        }
 
-      if (duration)
-       force_v4 = 1;
-
-      /* Is --pgp2 on, it's a v3 key, all the sigs on the key are
-         currently v3 and we're about to sign it with a v4 sig?  If
-         so, danger! */
-      if (PGP2 && all_v3 &&
-         (pk->version > 3 || force_v4) && primary_pk->version <= 3)
-       {
-         tty_fprintf (fp, _("You may not make an OpenPGP signature on a "
-                             "PGP 2.x key while in --pgp2 mode.\n"));
-         tty_fprintf (fp, _("This would make the key unusable in PGP 2.x.\n"));
-
-         if (opt.expert && !quick)
-           {
-             if (!cpr_get_answer_is_yes ("sign_uid.v4_on_v3_okay",
-                                         _("Are you sure you still "
-                                           "want to sign it? (y/N) ")))
-               continue;
-
-             all_v3 = 0;
-           }
-         else
-           continue;
-       }
-
       if (selfsig)
        ;
       else
@@ -1076,7 +1046,7 @@ sign_uids (estream_t fp,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
-                                        0x13, 0, force_v4 ? 4 : 0, 0, 0,
+                                        0x13, 0, 0, 0,
                                         keygen_add_std_prefs, primary_pk,
                                          NULL);
              else
@@ -1084,13 +1054,14 @@ sign_uids (estream_t fp,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
-                                        class, 0, force_v4 ? 4 : 0,
+                                        class, 0,
                                         timestamp, duration,
                                         sign_mk_attrib, &attrib,
                                          NULL);
              if (rc)
                {
-                 log_error (_("signing failed: %s\n"), g10_errstr (rc));
+                  write_status_error ("keysig", rc);
+                 log_error (_("signing failed: %s\n"), gpg_strerror (rc));
                  goto leave;
                }
 
@@ -1205,7 +1176,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
           if (err)
             log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
                       || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
-                     ? JNLIB_LOG_INFO : JNLIB_LOG_ERROR,
+                     ? GPGRT_LOG_INFO : GPGRT_LOG_ERROR,
                      _("key %s: error changing passphrase: %s\n"),
                        keystr_with_sub (keyid, subid),
                        gpg_strerror (err));
@@ -1231,7 +1202,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
  * Note:  This function does not work if there is more than one user ID.
  */
 static int
-fix_keyblock (KBNODE keyblock)
+fix_key_signature_order (KBNODE keyblock)
 {
   KBNODE node, last, subkey;
   int fixed = 0;
@@ -1271,6 +1242,27 @@ fix_keyblock (KBNODE keyblock)
 }
 
 
+/* Fix various problems in the keyblock.  Returns true if the keyblock
+   was changed.  Note that a pointer to the keyblock must be given and
+   the function may change it (i.e. replacing the first node).  */
+static int
+fix_keyblock (kbnode_t *keyblockp)
+{
+  int changed = 0;
+
+  if (fix_key_signature_order (*keyblockp))
+    changed++;
+  if (collapse_uids (keyblockp))
+    changed++;
+  reorder_keyblock (*keyblockp);
+  /* If we modified the keyblock, make sure the flags are right. */
+  if (changed)
+    merge_keys_and_selfsig (*keyblockp);
+
+  return changed;
+}
+
+
 static int
 parse_sign_type (const char *str, int *localsig, int *nonrevokesig,
                 int *trustsig)
@@ -1334,7 +1326,7 @@ enum cmdids
   cmdSHOWPREF,
   cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
   cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCHECKBKUPKEY,
-  cmdCLEAN, cmdMINIMIZE, cmdNOP
+  cmdCLEAN, cmdMINIMIZE, cmdGRIP, cmdNOP
 };
 
 static struct
@@ -1351,6 +1343,7 @@ static struct
   { "help", cmdHELP, 0, N_("show this help")},
   { "?", cmdHELP, 0, NULL},
   { "fpr", cmdFPR, 0, N_("show key fingerprint")},
+  { "grip", cmdGRIP, 0, N_("show the keygrip")},
   { "list", cmdLIST, 0, N_("list key and user IDs")},
   { "l", cmdLIST, 0, NULL},
   { "uid", cmdSELUID, 0, N_("select user ID N")},
@@ -1395,8 +1388,7 @@ static struct
     N_("change the expiration date for the key or selected subkeys")},
   { "primary", cmdPRIMARY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
     N_("flag the selected user ID as primary")},
-  { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK,
-    N_("toggle between the secret and public key listings")},
+  { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},  /* Dummy command.  */
   { "t", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},
   { "pref", cmdPREF, KEYEDIT_NOT_SK, N_("list preferences (expert)")},
   { "showpref", cmdSHOWPREF, KEYEDIT_NOT_SK, N_("list preferences (verbose)")},
@@ -1499,7 +1491,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
   char *answer = NULL;
   int redisplay = 1;
   int modified = 0;
-  int toggle;
+  int sec_shadowing = 0;
+  int run_subkey_warnings = 0;
   int have_commands = !!commands;
 
   if (opt.command_fd != -1)
@@ -1530,15 +1523,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
       log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
       goto leave;
     }
-  if (fix_keyblock (keyblock))
-    modified++;
-  if (collapse_uids (&keyblock))
+
+  if (fix_keyblock (&keyblock))
     modified++;
-  reorder_keyblock (keyblock);
-  /* We modified the keyblock, so let's make sure the flags are
-     right. */
-  if (modified)
-    merge_keys_and_selfsig (keyblock);
 
   /* See whether we have a matching secret key.  */
   if (seckey_check)
@@ -1548,8 +1535,6 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        tty_printf (_("Secret key is available.\n"));
     }
 
-  toggle = 0;
-
   /* Main command loop.  */
   for (;;)
     {
@@ -1562,10 +1547,19 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 
       if (redisplay && !quiet)
        {
-         show_key_with_all_names (NULL, keyblock, 0, 1, 0, 1, 0, 0);
+          /* Show using flags: with_revoker, with_subkeys.  */
+         show_key_with_all_names (ctrl, NULL, keyblock, 0, 1, 0, 1, 0, 0);
          tty_printf ("\n");
          redisplay = 0;
        }
+
+      if (run_subkey_warnings)
+        {
+          run_subkey_warnings = 0;
+          if (!count_selected_keys (keyblock))
+            subkey_expire_warning (keyblock);
+        }
+
       do
        {
          xfree (answer);
@@ -1641,13 +1635,6 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
              tty_printf (_("Need the secret key to do this.\n"));
              cmd = cmdNOP;
            }
-         else if (((cmds[i].flags & KEYEDIT_NOT_SK) && have_seckey && toggle)
-                  || ((cmds[i].flags & KEYEDIT_ONLY_SK) && have_seckey
-                      && !toggle))
-           {
-             tty_printf (_("Please use the command \"toggle\" first.\n"));
-             cmd = cmdNOP;
-           }
          else
            cmd = cmds[i].id;
        }
@@ -1679,7 +1666,13 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdFPR:
-         show_key_and_fingerprint (keyblock);
+         show_key_and_fingerprint
+            (keyblock, (*arg_string == '*'
+                        && (!arg_string[1] || spacep (arg_string + 1))));
+         break;
+
+       case cmdGRIP:
+         show_key_and_grip (keyblock);
          break;
 
        case cmdSELUID:
@@ -1705,7 +1698,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdCHECK:
-         check_all_keysigs (keyblock, count_selected_uids (keyblock));
+         check_all_keysigs (keyblock, count_selected_uids (keyblock),
+                             !strcmp (arg_string, "selfsig"));
          break;
 
        case cmdSIGN:
@@ -1754,7 +1748,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                break;
              }
 
-           sign_uids (NULL, keyblock, locusr, &modified,
+           sign_uids (ctrl, NULL, keyblock, locusr, &modified,
                       localsig, nonrevokesig, trustsig, interactive, 0);
          }
          break;
@@ -1768,12 +1762,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
              where we worked with a secret and a public keyring.  It
              is not necessary anymore but we keep this command for the
              sake of scripts using it.  */
-         toggle = !toggle;
          redisplay = 1;
          break;
 
        case cmdADDPHOTO:
-         if (RFC2440 || RFC1991 || PGP2)
+         if (RFC2440)
            {
              tty_printf (_("This command is not allowed while in %s mode.\n"),
                          compliance_option_string ());
@@ -1782,7 +1775,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          photo = 1;
          /* fall through */
        case cmdADDUID:
-         if (menu_adduid (keyblock, photo, arg_string))
+         if (menu_adduid (keyblock, photo, arg_string, NULL))
            {
              update_trust = 1;
              redisplay = 1;
@@ -1796,7 +1789,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            int n1;
 
            if (!(n1 = count_selected_uids (keyblock)))
-             tty_printf (_("You must select at least one user ID.\n"));
+              {
+                tty_printf (_("You must select at least one user ID.\n"));
+                if (!opt.expert)
+                  tty_printf (_("(Use the '%s' command.)\n"), "uid");
+              }
            else if (real_uids_left (keyblock) < 1)
              tty_printf (_("You can't delete the last user ID!\n"));
            else if (cpr_get_answer_is_yes
@@ -1816,7 +1813,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            int n1;
 
            if (!(n1 = count_selected_uids (keyblock)))
-             tty_printf (_("You must select at least one user ID.\n"));
+              {
+                tty_printf (_("You must select at least one user ID.\n"));
+                if (!opt.expert)
+                  tty_printf (_("(Use the '%s' command.)\n"), "uid");
+              }
            else if (menu_delsig (keyblock))
              {
                /* No redisplay here, because it may scroll away some
@@ -1876,8 +1877,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0))
                  {
                    redisplay = 1;
-                   /* Only the secret key has been modified; thus
-                       there is no need to set the modified flag.  */
+                   sec_shadowing = 1;
                  }
              }
          }
@@ -1925,11 +1925,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
            if (!err && pkt->pkttype != PKT_SECRET_KEY
                && pkt->pkttype != PKT_SECRET_SUBKEY)
-             err = G10ERR_NO_SECKEY;
+             err = GPG_ERR_NO_SECKEY;
            if (err)
              {
                tty_printf (_("Error reading backup key from '%s': %s\n"),
-                           fname, g10_errstr (err));
+                           fname, gpg_strerror (err));
                free_packet (pkt);
                xfree (pkt);
                break;
@@ -1963,7 +1963,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                if (card_store_subkey (node, 0))
                  {
                    redisplay = 1;
-                   /* FIXME:sec_modified = 1;*/
+                   sec_shadowing = 1;
                  }
              }
            release_kbnode (node);
@@ -1977,7 +1977,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            int n1;
 
            if (!(n1 = count_selected_keys (keyblock)))
-             tty_printf (_("You must select at least one key.\n"));
+              {
+                tty_printf (_("You must select at least one key.\n"));
+                if (!opt.expert)
+                  tty_printf (_("(Use the '%s' command.)\n"), "key");
+              }
            else if (!cpr_get_answer_is_yes
                      ("keyedit.remove.subkey.okay",
                       n1 > 1 ? _("Do you really want to delete the "
@@ -2013,7 +2017,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            int n1;
 
            if (!(n1 = count_selected_uids (keyblock)))
-             tty_printf (_("You must select at least one user ID.\n"));
+              {
+                tty_printf (_("You must select at least one user ID.\n"));
+                if (!opt.expert)
+                  tty_printf (_("(Use the '%s' command.)\n"), "uid");
+              }
            else if (cpr_get_answer_is_yes
                      ("keyedit.revoke.uid.okay",
                       n1 > 1 ? _("Really revoke all selected user IDs? (y/N) ")
@@ -2066,6 +2074,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          if (menu_expire (keyblock))
            {
              merge_keys_and_selfsig (keyblock);
+              run_subkey_warnings = 1;
              modified = 1;
              redisplay = 1;
            }
@@ -2101,7 +2110,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
              break;
            }
 
-         show_key_with_all_names (NULL, keyblock, 0, 0, 0, 1, 0, 0);
+         show_key_with_all_names (ctrl, NULL, keyblock, 0, 0, 0, 1, 0, 0);
          tty_printf ("\n");
          if (edit_ownertrust (find_kbnode (keyblock,
                                            PKT_PUBLIC_KEY)->pkt->pkt.
@@ -2221,7 +2230,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdQUIT:
          if (have_commands)
            goto leave;
-         if (!modified)
+         if (!modified && !sec_shadowing)
            goto leave;
          if (!cpr_get_answer_is_yes ("keyedit.save.okay",
                                      _("Save changes? (y/N) ")))
@@ -2239,11 +2248,22 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
               err = keydb_update_keyblock (kdbhd, keyblock);
               if (err)
                 {
-                  log_error (_("update failed: %s\n"), g10_errstr (err));
+                  log_error (_("update failed: %s\n"), gpg_strerror (err));
                   break;
                 }
            }
-         else
+
+         if (sec_shadowing)
+           {
+             err = agent_scd_learn (NULL, 1);
+             if (err)
+                {
+                  log_error (_("update failed: %s\n"), gpg_strerror (err));
+                  break;
+                }
+           }
+
+         if (!modified && !sec_shadowing)
            tty_printf (_("Key not changed so no update needed.\n"));
 
          if (update_trust)
@@ -2302,6 +2322,93 @@ leave:
 }
 
 
+/* Unattended adding of a new keyid.  USERNAME specifies the
+   key. NEWUID is the new user id to add to the key.  */
+void
+keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
+{
+  gpg_error_t err;
+  KEYDB_HANDLE kdbhd = NULL;
+  KEYDB_SEARCH_DESC desc;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
+  char *uidstring = NULL;
+
+  uidstring = xstrdup (newuid);
+  trim_spaces (uidstring);
+  if (!*uidstring)
+    {
+      log_error ("%s\n", gpg_strerror (GPG_ERR_INV_USER_ID));
+      goto leave;
+    }
+
+#ifdef HAVE_W32_SYSTEM
+  /* See keyedit_menu for why we need this.  */
+  check_trustdb_stale ();
+#endif
+
+  /* Search the key; we don't want the whole getkey stuff here.  */
+  kdbhd = keydb_new ();
+  err = classify_user_id (username, &desc, 1);
+  if (!err)
+    err = keydb_search (kdbhd, &desc, 1, NULL);
+  if (!err)
+    {
+      err = keydb_get_keyblock (kdbhd, &keyblock);
+      if (err)
+        {
+          log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
+          goto leave;
+        }
+      /* Now with the keyblock retrieved, search again to detect an
+         ambiguous specification.  We need to save the found state so
+         that we can do an update later.  */
+      keydb_push_found_state (kdbhd);
+      err = keydb_search (kdbhd, &desc, 1, NULL);
+      if (!err)
+        err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
+      else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+        err = 0;
+      keydb_pop_found_state (kdbhd);
+
+      if (!err)
+        {
+          /* We require the secret primary key to add a UID.  */
+          node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
+          if (!node)
+            BUG ();
+          err = agent_probe_secret_key (ctrl, node->pkt->pkt.public_key);
+        }
+    }
+  if (err)
+    {
+      log_error (_("secret key \"%s\" not found: %s\n"),
+                 username, gpg_strerror (err));
+      goto leave;
+    }
+
+  fix_keyblock (&keyblock);
+
+  if (menu_adduid (keyblock, 0, NULL, uidstring))
+    {
+      err = keydb_update_keyblock (kdbhd, keyblock);
+      if (err)
+        {
+          log_error (_("update failed: %s\n"), gpg_strerror (err));
+          goto leave;
+        }
+
+      if (update_trust)
+        revalidation_mark ();
+    }
+
+ leave:
+  xfree (uidstring);
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+}
+
+
 /* Unattended key signing function.  If the key specifified by FPR is
    availabale and FPR is the primary fingerprint all user ids of the
    user ids of the key are signed using the default signing key.  If
@@ -2345,11 +2452,6 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
       log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
       goto leave;
     }
-  if (fix_keyblock (keyblock))
-    modified++;
-  if (collapse_uids (&keyblock))
-    modified++;
-  reorder_keyblock (keyblock);
 
   /* Check that the primary fingerprint has been given. */
   {
@@ -2378,14 +2480,13 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
       }
   }
 
-  /* If we modified the keyblock, make sure the flags are right. */
-  if (modified)
-    merge_keys_and_selfsig (keyblock);
+  if (fix_keyblock (&keyblock))
+    modified++;
 
   /* Give some info in verbose.  */
   if (opt.verbose)
     {
-      show_key_with_all_names (es_stdout, keyblock, 0,
+      show_key_with_all_names (ctrl, es_stdout, keyblock, 0,
                                1/*with_revoker*/, 1/*with_fingerprint*/,
                                0, 0, 1);
       es_fflush (es_stdout);
@@ -2395,7 +2496,7 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
   if (pk->flags.revoked)
     {
       if (!opt.verbose)
-        show_key_with_all_names (es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
+        show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
       log_error ("%s%s", _("Key is revoked."), _("  Unable to sign.\n"));
       goto leave;
     }
@@ -2426,14 +2527,14 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
   if (uids && !any)
     {
       if (!opt.verbose)
-        show_key_with_all_names (es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
+        show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
       es_fflush (es_stdout);
       log_error ("%s  %s", _("No matching user IDs."), _("Nothing to sign.\n"));
       goto leave;
     }
 
   /* Sign. */
-  sign_uids (es_stdout, keyblock, locusr, &modified, local, 0, 0, 0, 1);
+  sign_uids (ctrl, es_stdout, keyblock, locusr, &modified, local, 0, 0, 0, 1);
   es_fflush (es_stdout);
 
   if (modified)
@@ -2659,12 +2760,13 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
    opt.with_colons is used.  It prints all available data in a easy to
    parse format and does not translate utf8 */
 static void
-show_key_with_all_names_colon (estream_t fp, kbnode_t keyblock)
+show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
 {
   KBNODE node;
   int i, j, ulti_hack = 0;
   byte pk_version = 0;
   PKT_public_key *primary = NULL;
+  int have_seckey;
 
   if (!fp)
     fp = es_stdout;
@@ -2685,9 +2787,13 @@ show_key_with_all_names_colon (estream_t fp, kbnode_t keyblock)
            }
 
          keyid_from_pk (pk, keyid);
+          have_seckey = !agent_probe_secret_key (ctrl, pk);
+
+          if (node->pkt->pkttype == PKT_PUBLIC_KEY)
+            es_fputs (have_seckey? "sec:" : "pub:", fp);
+          else
+            es_fputs (have_seckey? "ssb:" : "sub:", fp);
 
-         es_fputs (node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub:" : "sub:",
-                    fp);
          if (!pk->flags.valid)
            es_putc ('i', fp);
          else if (pk->flags.revoked)
@@ -2878,20 +2984,23 @@ show_names (estream_t fp,
  * tty (ignored in with-colons mode).
  */
 static void
-show_key_with_all_names (estream_t fp,
+show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                          KBNODE keyblock, int only_marked, int with_revoker,
                         int with_fpr, int with_subkeys, int with_prefs,
                          int nowarn)
 {
-  KBNODE node;
+  gpg_error_t err;
+  kbnode_t node;
   int i;
   int do_warn = 0;
+  int have_seckey = 0;
+  char *serialno = NULL;
   PKT_public_key *primary = NULL;
   char pkstrbuf[PUBKEY_STRING_SIZE];
 
   if (opt.with_colons)
     {
-      show_key_with_all_names_colon (fp, keyblock);
+      show_key_with_all_names_colon (ctrl, fp, keyblock);
       return;
     }
 
@@ -2969,13 +3078,33 @@ show_key_with_all_names (estream_t fp,
            }
 
          keyid_from_pk (pk, NULL);
-         tty_fprintf (fp, "%s%c %s/%s",
-                     node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" :
-                     node->pkt->pkttype == PKT_PUBLIC_SUBKEY ? "sub" :
-                     node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb",
-                     (node->flag & NODFLG_SELKEY) ? '*' : ' ',
-                      pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
-                     keystr (pk->keyid));
+
+          xfree (serialno);
+          serialno = NULL;
+          {
+            char *hexgrip;
+
+            err = hexkeygrip_from_pk (pk, &hexgrip);
+            if (err)
+              {
+                log_error ("error computing a keygrip: %s\n",
+                           gpg_strerror (err));
+                have_seckey = 0;
+              }
+            else
+              have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno);
+            xfree (hexgrip);
+          }
+
+         tty_fprintf
+            (fp, "%s%c %s/%s",
+             node->pkt->pkttype == PKT_PUBLIC_KEY && have_seckey? "sec" :
+             node->pkt->pkttype == PKT_PUBLIC_KEY ?               "pub" :
+             have_seckey ?                                        "ssb" :
+                                                                  "sub",
+             (node->flag & NODFLG_SELKEY) ? '*' : ' ',
+             pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
+             keystr (pk->keyid));
 
           if (opt.legacy_list_mode)
             tty_fprintf (fp, "  ");
@@ -2991,13 +3120,33 @@ show_key_with_all_names (estream_t fp,
          else
            tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
          tty_fprintf (fp, "  ");
-         tty_fprintf (fp, _("usage: %s"), usagestr_from_pk (pk));
+         tty_fprintf (fp, _("usage: %s"), usagestr_from_pk (pk, 1));
          tty_fprintf (fp, "\n");
 
-         if (pk->seckey_info
+          if (serialno)
+            {
+              /* The agent told us that a secret key is available and
+                 that it has been stored on a card.  */
+             tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
+                           _("card-no: "));
+              if (strlen (serialno) == 32
+                  && !strncmp (serialno, "D27600012401", 12))
+                {
+                  /* This is an OpenPGP card.  Print the relevant part.  */
+                  /* Example: D2760001240101010001000003470000 */
+                  /*                          xxxxyyyyyyyy     */
+                  tty_fprintf (fp, "%.*s %.*s\n",
+                               4, serialno+16, 8, serialno+20);
+                }
+              else
+                tty_fprintf (fp, "%s\n", serialno);
+
+            }
+         else if (pk->seckey_info
               && pk->seckey_info->is_protected
               && pk->seckey_info->s2k.mode == 1002)
            {
+              /* FIXME: Check wether this code path is still used.  */
              tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
                            _("card-no: "));
              if (pk->seckey_info->ivlen == 16
@@ -3069,13 +3218,17 @@ show_key_with_all_names (estream_t fp,
     tty_fprintf (fp, _("Please note that the shown key validity"
                        " is not necessarily correct\n"
                        "unless you restart the program.\n"));
+
+  xfree (serialno);
 }
 
 
 /* Display basic key information.  This function 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.*/
+   a secret key.  This function may be called with KEYBLOCK containing
+   secret keys and thus the printing of "pub" vs. "sec" does only
+   depend on the packet type and not by checking with gpg-agent.  */
 void
 show_basic_key_info (KBNODE keyblock)
 {
@@ -3127,10 +3280,11 @@ show_basic_key_info (KBNODE keyblock)
     }
 }
 
+
 static void
-show_key_and_fingerprint (KBNODE keyblock)
+show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys)
 {
-  KBNODE node;
+  kbnode_t node;
   PKT_public_key *pk = NULL;
   char pkstrbuf[PUBKEY_STRING_SIZE];
 
@@ -3154,6 +3308,56 @@ show_key_and_fingerprint (KBNODE keyblock)
   tty_printf ("\n");
   if (pk)
     print_fingerprint (NULL, pk, 2);
+  if (with_subkeys)
+    {
+      for (node = keyblock; node; node = node->next)
+        {
+          if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+            {
+              pk = node->pkt->pkt.public_key;
+              tty_printf ("sub   %s/%s %s [%s]\n",
+                          pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
+                          keystr_from_pk(pk),
+                          datestr_from_pk (pk),
+                          usagestr_from_pk (pk, 0));
+
+              print_fingerprint (NULL, pk, 4);
+            }
+        }
+    }
+}
+
+
+/* Show a listing of the primary and its subkeys along with their
+   keygrips.  */
+static void
+show_key_and_grip (kbnode_t keyblock)
+{
+  kbnode_t node;
+  PKT_public_key *pk = NULL;
+  char pkstrbuf[PUBKEY_STRING_SIZE];
+  char *hexgrip;
+
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_PUBLIC_KEY
+          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+        {
+          pk = node->pkt->pkt.public_key;
+          tty_printf ("%s   %s/%s %s [%s]\n",
+                      node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
+                      pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
+                      keystr_from_pk(pk),
+                      datestr_from_pk (pk),
+                      usagestr_from_pk (pk, 0));
+
+          if (!hexkeygrip_from_pk (pk, &hexgrip))
+            {
+              tty_printf ("      Keygrip: %s\n", hexgrip);
+              xfree (hexgrip);
+            }
+        }
+    }
 }
 
 
@@ -3192,12 +3396,68 @@ no_primary_warning (KBNODE keyblock)
 }
 
 
+/* Print a warning if the latest encryption subkey expires soon.  This
+   function is called after the expire data of the primary key has
+   been changed.  */
+static void
+subkey_expire_warning (kbnode_t keyblock)
+{
+  u32 curtime = make_timestamp ();
+  kbnode_t node;
+  PKT_public_key *pk;
+  /* u32 mainexpire = 0; */
+  u32 subexpire = 0;
+  u32 latest_date = 0;
+
+  for (node = keyblock; node; node = node->next)
+    {
+      /* if (node->pkt->pkttype == PKT_PUBLIC_KEY) */
+      /*   { */
+      /*     pk = node->pkt->pkt.public_key; */
+      /*     mainexpire = pk->expiredate; */
+      /*   } */
+
+      if (node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
+        continue;
+      pk = node->pkt->pkt.public_key;
+
+      if (!pk->flags.valid)
+        continue;
+      if (pk->flags.revoked)
+        continue;
+      if (pk->timestamp > curtime)
+        continue; /* Ignore future keys.  */
+      if (!(pk->pubkey_usage & PUBKEY_USAGE_ENC))
+        continue; /* Not an encryption key.  */
+
+      if (pk->timestamp > latest_date || (!pk->timestamp && !latest_date))
+        {
+          latest_date = pk->timestamp;
+          subexpire = pk->expiredate;
+        }
+    }
+
+  if (!subexpire)
+    return;  /* No valid subkey with an expiration time.  */
+
+  if (curtime + (10*86400) > subexpire)
+    {
+      log_info (_("WARNING: Your encryption subkey expires soon.\n"));
+      log_info (_("You may want to change its expiration date too.\n"));
+    }
+}
+
+
 /*
- * Ask for a new user id, add the self-signature and update the keyblock.
- * Return true if there is a new user id
+ * Ask for a new user id, add the self-signature, and update the
+ * keyblock.  If UIDSTRING is not NULL the user ID is generated
+ * unattended using that string.  UIDSTRING is expected to be utf-8
+ * encoded and white space trimmed.  Returns true if there is a new
+ * user id.
  */
 static int
-menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
+menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
+             const char *uidstring)
 {
   PKT_user_id *uid;
   PKT_public_key *pk = NULL;
@@ -3207,6 +3467,9 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
   KBNODE pub_where = NULL;
   gpg_error_t err;
 
+  if (photo && uidstring)
+    return 0;  /* Not allowed.  */
+
   for (node = pub_keyblock; node; pub_where = node, node = node->next)
     {
       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
@@ -3259,15 +3522,20 @@ menu_adduid (KBNODE pub_keyblock, int photo, const char *photo_name)
       uid = generate_photo_id (pk, photo_name);
     }
   else
-    uid = generate_user_id (pub_keyblock);
+    uid = generate_user_id (pub_keyblock, uidstring);
   if (!uid)
-    return 0;
+    {
+      if (uidstring)
+        log_error ("%s", _("Such a user ID already exists on this key!\n"));
+      return 0;
+    }
 
-  err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0, 0,
+  err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
                             keygen_add_std_prefs, pk, NULL);
   if (err)
     {
-      log_error ("signing failed: %s\n", g10_errstr (err));
+      write_status_error ("keysig", err);
+      log_error ("signing failed: %s\n", gpg_strerror (err));
       free_user_id (uid);
       return 0;
     }
@@ -3353,7 +3621,7 @@ menu_delsig (KBNODE pub_keyblock)
          else
            valid = print_and_check_one_sig (pub_keyblock, node,
                                             &inv_sig, &no_key, &other_err,
-                                            &selfsig, 1);
+                                            &selfsig, 1, 0);
 
          if (valid)
            {
@@ -3566,7 +3834,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
       if (rc)
        {
          log_error (_("key \"%s\" not found: %s\n"), answer,
-                    g10_errstr (rc));
+                    gpg_strerror (rc));
          xfree (answer);
          continue;
        }
@@ -3647,13 +3915,12 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
       break;
     }
 
-  /* The 1F signature must be at least v4 to carry the revocation key
-     subpacket. */
-  rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 4, 0, 0,
+  rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
                           keygen_add_revkey, &revkey, NULL);
   if (rc)
     {
-      log_error ("signing failed: %s\n", g10_errstr (rc));
+      write_status_error ("keysig", rc);
+      log_error ("signing failed: %s\n", gpg_strerror (rc));
       goto fail;
     }
 
@@ -3757,7 +4024,7 @@ menu_expire (KBNODE pub_keyblock)
              if (rc)
                {
                  log_error ("make_keysig_packet failed: %s\n",
-                            g10_errstr (rc));
+                            gpg_strerror (rc));
                  return 0;
                }
 
@@ -3873,13 +4140,13 @@ menu_backsign (KBNODE pub_keyblock)
          else
            {
              log_error ("update_keysig_packet failed: %s\n",
-                        g10_errstr (rc));
+                        gpg_strerror (rc));
              break;
            }
        }
       else
        {
-         log_error ("make_backsig failed: %s\n", g10_errstr (rc));
+         log_error ("make_backsig failed: %s\n", gpg_strerror (rc));
          break;
        }
     }
@@ -4015,7 +4282,7 @@ menu_set_primary_uid (KBNODE pub_keyblock)
                      if (rc)
                        {
                          log_error ("update_keysig_packet failed: %s\n",
-                                    g10_errstr (rc));
+                                    gpg_strerror (rc));
                          return 0;
                        }
                      /* replace the packet */
@@ -4104,7 +4371,7 @@ menu_set_preferences (KBNODE pub_keyblock)
                  if (rc)
                    {
                      log_error ("update_keysig_packet failed: %s\n",
-                                g10_errstr (rc));
+                                gpg_strerror (rc));
                      return 0;
                    }
                  /* replace the packet */
@@ -4156,7 +4423,7 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
     {
       struct keyserver_spec *keyserver = NULL;
       /* Sanity check the format */
-      keyserver = parse_keyserver_uri (answer, 1, NULL, 0);
+      keyserver = parse_keyserver_uri (answer, 1);
       xfree (answer);
       if (!keyserver)
        {
@@ -4239,7 +4506,7 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
                  if (rc)
                    {
                      log_error ("update_keysig_packet failed: %s\n",
-                                g10_errstr (rc));
+                                gpg_strerror (rc));
                      xfree (uri);
                      return 0;
                    }
@@ -4438,7 +4705,7 @@ menu_set_notation (const char *string, KBNODE pub_keyblock)
                  if (rc)
                    {
                      log_error ("update_keysig_packet failed: %s\n",
-                                g10_errstr (rc));
+                                gpg_strerror (rc));
                      free_notation (notation);
                      xfree (user);
                      return 0;
@@ -4724,11 +4991,11 @@ ask_revoke_sig (KBNODE keyblock, KBNODE node)
        printf ("uat:::::::::%u %lu", uid->numattribs, uid->attrib_len);
       else
        {
-         printf ("uid:::::::::");
+         es_printf ("uid:::::::::");
          es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
        }
 
-      printf ("\n");
+      es_printf ("\n");
 
       print_and_check_one_sig_colon (keyblock, node, NULL, NULL, NULL, NULL,
                                     1);
@@ -4939,12 +5206,13 @@ reloop:                 /* (must use this, because we are modifing the list) */
        }
       rc = make_keysig_packet (&sig, primary_pk,
                               unode->pkt->pkt.user_id,
-                              NULL, signerkey, 0x30, 0, 0, 0, 0,
+                              NULL, signerkey, 0x30, 0, 0, 0,
                                sign_mk_attrib, &attrib, NULL);
       free_public_key (signerkey);
       if (rc)
        {
-         log_error (_("signing failed: %s\n"), g10_errstr (rc));
+          write_status_error ("keysig", rc);
+         log_error (_("signing failed: %s\n"), gpg_strerror (rc));
          release_revocation_reason_info (reason);
          return changed;
        }
@@ -5031,11 +5299,12 @@ menu_revuid (KBNODE pub_keyblock)
            node->flag &= ~NODFLG_SELUID;
 
            rc = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x30, 0,
-                                    (reason == NULL) ? 3 : 0, timestamp, 0,
+                                    timestamp, 0,
                                     sign_mk_attrib, &attrib, NULL);
            if (rc)
              {
-               log_error (_("signing failed: %s\n"), g10_errstr (rc));
+                write_status_error ("keysig", rc);
+               log_error (_("signing failed: %s\n"), gpg_strerror (rc));
                goto leave;
              }
            else
@@ -5095,11 +5364,12 @@ menu_revkey (KBNODE pub_keyblock)
     return 0;
 
   rc = make_keysig_packet (&sig, pk, NULL, NULL, pk,
-                          0x20, 0, opt.force_v4_certs ? 4 : 0, 0, 0,
+                          0x20, 0, 0, 0,
                           revocation_reason_build_cb, reason, NULL);
   if (rc)
     {
-      log_error (_("signing failed: %s\n"), g10_errstr (rc));
+      write_status_error ("keysig", rc);
+      log_error (_("signing failed: %s\n"), gpg_strerror (rc));
       goto scram;
     }
 
@@ -5156,11 +5426,12 @@ menu_revsubkey (KBNODE pub_keyblock)
 
          node->flag &= ~NODFLG_SELKEY;
          rc = make_keysig_packet (&sig, mainpk, NULL, subpk, mainpk,
-                                  0x28, 0, 0, 0, 0, sign_mk_attrib, &attrib,
+                                  0x28, 0, 0, 0, sign_mk_attrib, &attrib,
                                    NULL);
          if (rc)
            {
-             log_error (_("signing failed: %s\n"), g10_errstr (rc));
+              write_status_error ("keysig", rc);
+             log_error (_("signing failed: %s\n"), gpg_strerror (rc));
              release_revocation_reason_info (reason);
              return changed;
            }