LCOV - code coverage report
Current view: top level - g10 - keyedit.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 2534 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 53 0.0 %

          Line data    Source code
       1             : /* keyedit.c - Edit properties of a key
       2             :  * Copyright (C) 1998-2010 Free Software Foundation, Inc.
       3             :  * Copyright (C) 1998-2015 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #include <assert.h>
      27             : #include <ctype.h>
      28             : #ifdef HAVE_LIBREADLINE
      29             : # define GNUPG_LIBREADLINE_H_INCLUDED
      30             : # include <readline/readline.h>
      31             : #endif
      32             : 
      33             : #include "gpg.h"
      34             : #include "options.h"
      35             : #include "packet.h"
      36             : #include "status.h"
      37             : #include "iobuf.h"
      38             : #include "keydb.h"
      39             : #include "photoid.h"
      40             : #include "util.h"
      41             : #include "main.h"
      42             : #include "trustdb.h"
      43             : #include "filter.h"
      44             : #include "ttyio.h"
      45             : #include "status.h"
      46             : #include "i18n.h"
      47             : #include "keyserver-internal.h"
      48             : #include "call-agent.h"
      49             : #include "host2net.h"
      50             : #include "tofu.h"
      51             : 
      52             : static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
      53             :                         int verbose);
      54             : static void show_names (estream_t fp, KBNODE keyblock, PKT_public_key * pk,
      55             :                         unsigned int flag, int with_prefs);
      56             : static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
      57             :                                      KBNODE keyblock, int only_marked,
      58             :                                      int with_revoker, int with_fpr,
      59             :                                      int with_subkeys, int with_prefs,
      60             :                                      int nowarn);
      61             : static void show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys);
      62             : static void show_key_and_grip (kbnode_t keyblock);
      63             : static void subkey_expire_warning (kbnode_t keyblock);
      64             : static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name,
      65             :                         const char *uidstr);
      66             : static void menu_deluid (KBNODE pub_keyblock);
      67             : static int menu_delsig (KBNODE pub_keyblock);
      68             : static int menu_clean (KBNODE keyblock, int self_only);
      69             : static void menu_delkey (KBNODE pub_keyblock);
      70             : static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
      71             : static int menu_expire (KBNODE pub_keyblock);
      72             : static int menu_backsign (KBNODE pub_keyblock);
      73             : static int menu_set_primary_uid (KBNODE pub_keyblock);
      74             : static int menu_set_preferences (KBNODE pub_keyblock);
      75             : static int menu_set_keyserver_url (const char *url, KBNODE pub_keyblock);
      76             : static int menu_set_notation (const char *string, KBNODE pub_keyblock);
      77             : static int menu_select_uid (KBNODE keyblock, int idx);
      78             : static int menu_select_uid_namehash (KBNODE keyblock, const char *namehash);
      79             : static int menu_select_key (KBNODE keyblock, int idx);
      80             : static int count_uids (KBNODE keyblock);
      81             : static int count_uids_with_flag (KBNODE keyblock, unsigned flag);
      82             : static int count_keys_with_flag (KBNODE keyblock, unsigned flag);
      83             : static int count_selected_uids (KBNODE keyblock);
      84             : static int real_uids_left (KBNODE keyblock);
      85             : static int count_selected_keys (KBNODE keyblock);
      86             : static int menu_revsig (KBNODE keyblock);
      87             : static int menu_revuid (KBNODE keyblock);
      88             : static int menu_revkey (KBNODE pub_keyblock);
      89             : static int menu_revsubkey (KBNODE pub_keyblock);
      90             : #ifndef NO_TRUST_MODELS
      91             : static int enable_disable_key (KBNODE keyblock, int disable);
      92             : #endif /*!NO_TRUST_MODELS*/
      93             : static void menu_showphoto (KBNODE keyblock);
      94             : 
      95             : static int update_trust = 0;
      96             : 
      97             : #define CONTROL_D ('D' - 'A' + 1)
      98             : 
      99             : #define NODFLG_BADSIG (1<<0)      /* Bad signature.  */
     100             : #define NODFLG_NOKEY  (1<<1)      /* No public key.  */
     101             : #define NODFLG_SIGERR (1<<2)      /* Other sig error.  */
     102             : 
     103             : #define NODFLG_MARK_A (1<<4)      /* Temporary mark.  */
     104             : #define NODFLG_DELSIG (1<<5)      /* To be deleted.  */
     105             : 
     106             : #define NODFLG_SELUID (1<<8)      /* Indicate the selected userid. */
     107             : #define NODFLG_SELKEY (1<<9)      /* Indicate the selected key.  */
     108             : #define NODFLG_SELSIG (1<<10)     /* Indicate a selected signature.  */
     109             : 
     110             : struct sign_attrib
     111             : {
     112             :   int non_exportable, non_revocable;
     113             :   struct revocation_reason_info *reason;
     114             :   byte trust_depth, trust_value;
     115             :   char *trust_regexp;
     116             : };
     117             : 
     118             : 
     119             : 
     120             : /* TODO: Fix duplicated code between here and the check-sigs/list-sigs
     121             :    code in keylist.c. */
     122             : static int
     123           0 : print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
     124             :                                int *inv_sigs, int *no_key, int *oth_err,
     125             :                                int *is_selfsig, int print_without_key)
     126             : {
     127           0 :   PKT_signature *sig = node->pkt->pkt.signature;
     128             :   int rc, sigrc;
     129             : 
     130             :   /* TODO: Make sure a cached sig record here still has the pk that
     131             :      issued it.  See also keylist.c:list_keyblock_print */
     132             : 
     133           0 :   rc = check_key_signature (keyblock, node, is_selfsig);
     134           0 :   switch (gpg_err_code (rc))
     135             :     {
     136             :     case 0:
     137           0 :       node->flag &= ~(NODFLG_BADSIG | NODFLG_NOKEY | NODFLG_SIGERR);
     138           0 :       sigrc = '!';
     139           0 :       break;
     140             :     case GPG_ERR_BAD_SIGNATURE:
     141           0 :       node->flag = NODFLG_BADSIG;
     142           0 :       sigrc = '-';
     143           0 :       if (inv_sigs)
     144           0 :         ++ * inv_sigs;
     145           0 :       break;
     146             :     case GPG_ERR_NO_PUBKEY:
     147             :     case GPG_ERR_UNUSABLE_PUBKEY:
     148           0 :       node->flag = NODFLG_NOKEY;
     149           0 :       sigrc = '?';
     150           0 :       if (no_key)
     151           0 :         ++ * no_key;
     152           0 :       break;
     153             :     default:
     154           0 :       node->flag = NODFLG_SIGERR;
     155           0 :       sigrc = '%';
     156           0 :       if (oth_err)
     157           0 :         ++ * oth_err;
     158           0 :       break;
     159             :     }
     160             : 
     161           0 :   if (sigrc != '?' || print_without_key)
     162             :     {
     163           0 :       es_printf ("sig:%c::%d:%08lX%08lX:%lu:%lu:",
     164           0 :                  sigrc, sig->pubkey_algo, (ulong) sig->keyid[0],
     165           0 :                  (ulong) sig->keyid[1], (ulong) sig->timestamp,
     166           0 :                  (ulong) sig->expiredate);
     167             : 
     168           0 :       if (sig->trust_depth || sig->trust_value)
     169           0 :         es_printf ("%d %d", sig->trust_depth, sig->trust_value);
     170             : 
     171           0 :       es_printf (":");
     172             : 
     173           0 :       if (sig->trust_regexp)
     174           0 :         es_write_sanitized (es_stdout,
     175           0 :                             sig->trust_regexp, strlen (sig->trust_regexp),
     176             :                             ":", NULL);
     177             : 
     178           0 :       es_printf ("::%02x%c\n", sig->sig_class,
     179           0 :                  sig->flags.exportable ? 'x' : 'l');
     180             : 
     181           0 :       if (opt.show_subpackets)
     182           0 :         print_subpackets_colon (sig);
     183             :     }
     184             : 
     185           0 :   return (sigrc == '!');
     186             : }
     187             : 
     188             : 
     189             : /*
     190             :  * Print information about a signature, check it and return true if
     191             :  * the signature is okay.  NODE must be a signature packet.  With
     192             :  * EXTENDED set all possible signature list options will always be
     193             :  * printed.
     194             :  */
     195             : static int
     196           0 : print_and_check_one_sig (KBNODE keyblock, KBNODE node,
     197             :                          int *inv_sigs, int *no_key, int *oth_err,
     198             :                          int *is_selfsig, int print_without_key, int extended)
     199             : {
     200           0 :   PKT_signature *sig = node->pkt->pkt.signature;
     201             :   int rc, sigrc;
     202           0 :   int is_rev = sig->sig_class == 0x30;
     203             : 
     204             :   /* TODO: Make sure a cached sig record here still has the pk that
     205             :      issued it.  See also keylist.c:list_keyblock_print */
     206             : 
     207           0 :   rc = check_key_signature (keyblock, node, is_selfsig);
     208           0 :   switch (gpg_err_code (rc))
     209             :     {
     210             :     case 0:
     211           0 :       node->flag &= ~(NODFLG_BADSIG | NODFLG_NOKEY | NODFLG_SIGERR);
     212           0 :       sigrc = '!';
     213           0 :       break;
     214             :     case GPG_ERR_BAD_SIGNATURE:
     215           0 :       node->flag = NODFLG_BADSIG;
     216           0 :       sigrc = '-';
     217           0 :       if (inv_sigs)
     218           0 :         ++ * inv_sigs;
     219           0 :       break;
     220             :     case GPG_ERR_NO_PUBKEY:
     221             :     case GPG_ERR_UNUSABLE_PUBKEY:
     222           0 :       node->flag = NODFLG_NOKEY;
     223           0 :       sigrc = '?';
     224           0 :       if (no_key)
     225           0 :         ++ * no_key;
     226           0 :       break;
     227             :     default:
     228           0 :       node->flag = NODFLG_SIGERR;
     229           0 :       sigrc = '%';
     230           0 :       if (oth_err)
     231           0 :         ++ * oth_err;
     232           0 :       break;
     233             :     }
     234           0 :   if (sigrc != '?' || print_without_key)
     235             :     {
     236           0 :       tty_printf ("%s%c%c %c%c%c%c%c%c %s %s",
     237             :                   is_rev ? "rev" : "sig", sigrc,
     238           0 :                   (sig->sig_class - 0x10 > 0 &&
     239           0 :                    sig->sig_class - 0x10 <
     240           0 :                    4) ? '0' + sig->sig_class - 0x10 : ' ',
     241           0 :                   sig->flags.exportable ? ' ' : 'L',
     242           0 :                   sig->flags.revocable ? ' ' : 'R',
     243           0 :                   sig->flags.policy_url ? 'P' : ' ',
     244           0 :                   sig->flags.notation ? 'N' : ' ',
     245           0 :                   sig->flags.expired ? 'X' : ' ',
     246           0 :                   (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
     247           0 :                                                   0) ? '0' +
     248           0 :                   sig->trust_depth : ' ',
     249           0 :                   keystr (sig->keyid),
     250             :                   datestr_from_sig (sig));
     251           0 :       if ((opt.list_options & LIST_SHOW_SIG_EXPIRE) || extended )
     252           0 :         tty_printf (" %s", expirestr_from_sig (sig));
     253           0 :       tty_printf ("  ");
     254           0 :       if (sigrc == '%')
     255           0 :         tty_printf ("[%s] ", gpg_strerror (rc));
     256           0 :       else if (sigrc == '?')
     257             :         ;
     258           0 :       else if (*is_selfsig)
     259             :         {
     260           0 :           tty_printf (is_rev ? _("[revocation]") : _("[self-signature]"));
     261           0 :           if (extended && sig->flags.chosen_selfsig)
     262           0 :             tty_printf ("*");
     263             :         }
     264             :       else
     265             :         {
     266             :           size_t n;
     267           0 :           char *p = get_user_id (sig->keyid, &n);
     268           0 :           tty_print_utf8_string2 (NULL, p, n,
     269           0 :                                   opt.screen_columns - keystrlen () - 26 -
     270           0 :                                   ((opt.
     271           0 :                                     list_options & LIST_SHOW_SIG_EXPIRE) ? 11
     272             :                                    : 0));
     273           0 :           xfree (p);
     274             :         }
     275           0 :       tty_printf ("\n");
     276             : 
     277           0 :       if (sig->flags.policy_url
     278           0 :           && ((opt.list_options & LIST_SHOW_POLICY_URLS) || extended))
     279           0 :         show_policy_url (sig, 3, 0);
     280             : 
     281           0 :       if (sig->flags.notation
     282           0 :           && ((opt.list_options & LIST_SHOW_NOTATIONS) || extended))
     283           0 :         show_notation (sig, 3, 0,
     284           0 :                        ((opt.
     285           0 :                          list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0) +
     286           0 :                        ((opt.
     287           0 :                          list_options & LIST_SHOW_USER_NOTATIONS) ? 2 : 0));
     288             : 
     289           0 :       if (sig->flags.pref_ks
     290           0 :           && ((opt.list_options & LIST_SHOW_KEYSERVER_URLS) || extended))
     291           0 :         show_keyserver_url (sig, 3, 0);
     292             : 
     293           0 :       if (extended)
     294             :         {
     295           0 :           PKT_public_key *pk = keyblock->pkt->pkt.public_key;
     296             :           const unsigned char *s;
     297             : 
     298           0 :           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL);
     299           0 :           if (s && *s)
     300           0 :             tty_printf ("             [primary]\n");
     301             : 
     302           0 :           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
     303           0 :           if (s && buf32_to_u32 (s))
     304           0 :             tty_printf ("             [expires: %s]\n",
     305           0 :                         isotimestamp (pk->timestamp + buf32_to_u32 (s)));
     306             :         }
     307             :     }
     308             : 
     309           0 :   return (sigrc == '!');
     310             : }
     311             : 
     312             : 
     313             : 
     314             : /*
     315             :  * Check the keysigs and set the flags to indicate errors.
     316             :  * Returns true if error found.
     317             :  */
     318             : static int
     319           0 : check_all_keysigs (KBNODE keyblock, int only_selected, int only_selfsigs)
     320             : {
     321             :   KBNODE kbctx;
     322             :   KBNODE node;
     323           0 :   int inv_sigs = 0;
     324           0 :   int no_key = 0;
     325           0 :   int oth_err = 0;
     326           0 :   int has_selfsig = 0;
     327           0 :   int mis_selfsig = 0;
     328           0 :   int selected = !only_selected;
     329           0 :   int anyuid = 0;
     330             :   u32 keyid[2];
     331             : 
     332           0 :   for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
     333             :     {
     334           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
     335             :         {
     336           0 :           if (only_selfsigs)
     337           0 :             keyid_from_pk (node->pkt->pkt.public_key, keyid);
     338             :         }
     339           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
     340             :         {
     341           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
     342             : 
     343           0 :           if (only_selected)
     344           0 :             selected = (node->flag & NODFLG_SELUID);
     345           0 :           if (selected)
     346             :             {
     347           0 :               tty_printf ("uid  ");
     348           0 :               tty_print_utf8_string (uid->name, uid->len);
     349           0 :               tty_printf ("\n");
     350           0 :               if (anyuid && !has_selfsig)
     351           0 :                 mis_selfsig++;
     352           0 :               has_selfsig = 0;
     353           0 :               anyuid = 1;
     354             :             }
     355             :         }
     356           0 :       else if (selected && node->pkt->pkttype == PKT_SIGNATURE
     357           0 :                && ((node->pkt->pkt.signature->sig_class & ~3) == 0x10
     358           0 :                    || node->pkt->pkt.signature->sig_class == 0x30))
     359             :         {
     360             :           int selfsig;
     361           0 :           PKT_signature *sig = node->pkt->pkt.signature;
     362             : 
     363           0 :           if (only_selfsigs
     364           0 :               && !(keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]))
     365             :             ;  /* Not a selfsig but we want only selfsigs - skip.  */
     366           0 :           else if (print_and_check_one_sig (keyblock, node, &inv_sigs,
     367             :                                             &no_key, &oth_err, &selfsig,
     368             :                                             0, only_selfsigs))
     369             :             {
     370           0 :               if (selfsig)
     371           0 :                 has_selfsig = 1;
     372             :             }
     373             :           /* Hmmm: should we update the trustdb here? */
     374             :         }
     375             :     }
     376           0 :   if (!has_selfsig)
     377           0 :     mis_selfsig++;
     378           0 :   if (inv_sigs == 1)
     379           0 :     tty_printf (_("1 bad signature\n"));
     380           0 :   else if (inv_sigs)
     381           0 :     tty_printf (_("%d bad signatures\n"), inv_sigs);
     382           0 :   if (no_key == 1)
     383           0 :     tty_printf (_("1 signature not checked due to a missing key\n"));
     384           0 :   else if (no_key)
     385           0 :     tty_printf (_("%d signatures not checked due to missing keys\n"), no_key);
     386           0 :   if (oth_err == 1)
     387           0 :     tty_printf (_("1 signature not checked due to an error\n"));
     388           0 :   else if (oth_err)
     389           0 :     tty_printf (_("%d signatures not checked due to errors\n"), oth_err);
     390           0 :   if (mis_selfsig == 1)
     391           0 :     tty_printf (_("1 user ID without valid self-signature detected\n"));
     392           0 :   else if (mis_selfsig)
     393           0 :     tty_printf (_("%d user IDs without valid self-signatures detected\n"),
     394             :                 mis_selfsig);
     395             : 
     396           0 :   return inv_sigs || no_key || oth_err || mis_selfsig;
     397             : }
     398             : 
     399             : 
     400             : static int
     401           0 : sign_mk_attrib (PKT_signature * sig, void *opaque)
     402             : {
     403           0 :   struct sign_attrib *attrib = opaque;
     404             :   byte buf[8];
     405             : 
     406           0 :   if (attrib->non_exportable)
     407             :     {
     408           0 :       buf[0] = 0;               /* not exportable */
     409           0 :       build_sig_subpkt (sig, SIGSUBPKT_EXPORTABLE, buf, 1);
     410             :     }
     411             : 
     412           0 :   if (attrib->non_revocable)
     413             :     {
     414           0 :       buf[0] = 0;               /* not revocable */
     415           0 :       build_sig_subpkt (sig, SIGSUBPKT_REVOCABLE, buf, 1);
     416             :     }
     417             : 
     418           0 :   if (attrib->reason)
     419           0 :     revocation_reason_build_cb (sig, attrib->reason);
     420             : 
     421           0 :   if (attrib->trust_depth)
     422             :     {
     423             :       /* Not critical.  If someone doesn't understand trust sigs,
     424             :          this can still be a valid regular signature. */
     425           0 :       buf[0] = attrib->trust_depth;
     426           0 :       buf[1] = attrib->trust_value;
     427           0 :       build_sig_subpkt (sig, SIGSUBPKT_TRUST, buf, 2);
     428             : 
     429             :       /* Critical.  If someone doesn't understands regexps, this
     430             :          whole sig should be invalid.  Note the +1 for the length -
     431             :          regexps are null terminated. */
     432           0 :       if (attrib->trust_regexp)
     433           0 :         build_sig_subpkt (sig, SIGSUBPKT_FLAG_CRITICAL | SIGSUBPKT_REGEXP,
     434           0 :                           attrib->trust_regexp,
     435           0 :                           strlen (attrib->trust_regexp) + 1);
     436             :     }
     437             : 
     438           0 :   return 0;
     439             : }
     440             : 
     441             : 
     442             : static void
     443           0 : trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
     444             : {
     445             :   char *p;
     446             : 
     447           0 :   *trust_value = 0;
     448           0 :   *trust_depth = 0;
     449           0 :   *regexp = NULL;
     450             : 
     451             :   /* Same string as pkclist.c:do_edit_ownertrust */
     452           0 :   tty_printf (_
     453             :               ("Please decide how far you trust this user to correctly verify"
     454             :                " other users' keys\n(by looking at passports, checking"
     455             :                " fingerprints from different sources, etc.)\n"));
     456           0 :   tty_printf ("\n");
     457           0 :   tty_printf (_("  %d = I trust marginally\n"), 1);
     458           0 :   tty_printf (_("  %d = I trust fully\n"), 2);
     459           0 :   tty_printf ("\n");
     460             : 
     461           0 :   while (*trust_value == 0)
     462             :     {
     463           0 :       p = cpr_get ("trustsig_prompt.trust_value", _("Your selection? "));
     464           0 :       trim_spaces (p);
     465           0 :       cpr_kill_prompt ();
     466             :       /* 60 and 120 are as per RFC2440 */
     467           0 :       if (p[0] == '1' && !p[1])
     468           0 :         *trust_value = 60;
     469           0 :       else if (p[0] == '2' && !p[1])
     470           0 :         *trust_value = 120;
     471           0 :       xfree (p);
     472             :     }
     473             : 
     474           0 :   tty_printf ("\n");
     475             : 
     476           0 :   tty_printf (_("Please enter the depth of this trust signature.\n"
     477             :                 "A depth greater than 1 allows the key you are signing to make\n"
     478             :                 "trust signatures on your behalf.\n"));
     479           0 :   tty_printf ("\n");
     480             : 
     481           0 :   while (*trust_depth == 0)
     482             :     {
     483           0 :       p = cpr_get ("trustsig_prompt.trust_depth", _("Your selection? "));
     484           0 :       trim_spaces (p);
     485           0 :       cpr_kill_prompt ();
     486           0 :       *trust_depth = atoi (p);
     487           0 :       xfree (p);
     488             :     }
     489             : 
     490           0 :   tty_printf ("\n");
     491             : 
     492           0 :   tty_printf (_("Please enter a domain to restrict this signature, "
     493             :                 "or enter for none.\n"));
     494             : 
     495           0 :   tty_printf ("\n");
     496             : 
     497           0 :   p = cpr_get ("trustsig_prompt.trust_regexp", _("Your selection? "));
     498           0 :   trim_spaces (p);
     499           0 :   cpr_kill_prompt ();
     500             : 
     501           0 :   if (strlen (p) > 0)
     502             :     {
     503           0 :       char *q = p;
     504           0 :       int regexplen = 100, ind;
     505             : 
     506           0 :       *regexp = xmalloc (regexplen);
     507             : 
     508             :       /* Now mangle the domain the user entered into a regexp.  To do
     509             :          this, \-escape everything that isn't alphanumeric, and attach
     510             :          "<[^>]+[@.]" to the front, and ">$" to the end. */
     511             : 
     512           0 :       strcpy (*regexp, "<[^>]+[@.]");
     513           0 :       ind = strlen (*regexp);
     514             : 
     515           0 :       while (*q)
     516             :         {
     517           0 :           if (!((*q >= 'A' && *q <= 'Z')
     518           0 :                 || (*q >= 'a' && *q <= 'z') || (*q >= '0' && *q <= '9')))
     519           0 :             (*regexp)[ind++] = '\\';
     520             : 
     521           0 :           (*regexp)[ind++] = *q;
     522             : 
     523           0 :           if ((regexplen - ind) < 3)
     524             :             {
     525           0 :               regexplen += 100;
     526           0 :               *regexp = xrealloc (*regexp, regexplen);
     527             :             }
     528             : 
     529           0 :           q++;
     530             :         }
     531             : 
     532           0 :       (*regexp)[ind] = '\0';
     533           0 :       strcat (*regexp, ">$");
     534             :     }
     535             : 
     536           0 :   xfree (p);
     537           0 :   tty_printf ("\n");
     538           0 : }
     539             : 
     540             : 
     541             : /*
     542             :  * Loop over all LOCUSR and and sign the uids after asking.  If no
     543             :  * user id is marked, all user ids will be signed; if some user_ids
     544             :  * are marked only those will be signed.  If QUICK is true the
     545             :  * function won't ask the user and use sensible defaults.
     546             :  */
     547             : static int
     548           0 : sign_uids (ctrl_t ctrl, estream_t fp,
     549             :            kbnode_t keyblock, strlist_t locusr, int *ret_modified,
     550             :            int local, int nonrevocable, int trust, int interactive,
     551             :            int quick)
     552             : {
     553           0 :   int rc = 0;
     554           0 :   SK_LIST sk_list = NULL;
     555           0 :   SK_LIST sk_rover = NULL;
     556           0 :   PKT_public_key *pk = NULL;
     557             :   KBNODE node, uidnode;
     558           0 :   PKT_public_key *primary_pk = NULL;
     559           0 :   int select_all = !count_selected_uids (keyblock) || interactive;
     560             : 
     561             :   /* Build a list of all signators.
     562             :    *
     563             :    * We use the CERT flag to request the primary which must always
     564             :    * be one which is capable of signing keys.  I can't see a reason
     565             :    * why to sign keys using a subkey.  Implementation of USAGE_CERT
     566             :    * is just a hack in getkey.c and does not mean that a subkey
     567             :    * marked as certification capable will be used. */
     568           0 :   rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_CERT);
     569           0 :   if (rc)
     570           0 :     goto leave;
     571             : 
     572             :   /* Loop over all signators.  */
     573           0 :   for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
     574             :     {
     575             :       u32 sk_keyid[2], pk_keyid[2];
     576           0 :       char *p, *trust_regexp = NULL;
     577           0 :       int class = 0, selfsig = 0;
     578           0 :       u32 duration = 0, timestamp = 0;
     579           0 :       byte trust_depth = 0, trust_value = 0;
     580             : 
     581           0 :       pk = sk_rover->pk;
     582           0 :       keyid_from_pk (pk, sk_keyid);
     583             : 
     584             :       /* Set mark A for all selected user ids.  */
     585           0 :       for (node = keyblock; node; node = node->next)
     586             :         {
     587           0 :           if (select_all || (node->flag & NODFLG_SELUID))
     588           0 :             node->flag |= NODFLG_MARK_A;
     589             :           else
     590           0 :             node->flag &= ~NODFLG_MARK_A;
     591             :         }
     592             : 
     593             :       /* Reset mark for uids which are already signed.  */
     594           0 :       uidnode = NULL;
     595           0 :       for (node = keyblock; node; node = node->next)
     596             :         {
     597           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
     598             :             {
     599           0 :               primary_pk = node->pkt->pkt.public_key;
     600           0 :               keyid_from_pk (primary_pk, pk_keyid);
     601             : 
     602             :               /* Is this a self-sig? */
     603           0 :               if (pk_keyid[0] == sk_keyid[0] && pk_keyid[1] == sk_keyid[1])
     604           0 :                 selfsig = 1;
     605             :             }
     606           0 :           else if (node->pkt->pkttype == PKT_USER_ID)
     607             :             {
     608           0 :               uidnode = (node->flag & NODFLG_MARK_A) ? node : NULL;
     609           0 :               if (uidnode)
     610             :                 {
     611           0 :                   int yesreally = 0;
     612             :                   char *user;
     613             : 
     614           0 :                   user = utf8_to_native (uidnode->pkt->pkt.user_id->name,
     615           0 :                                          uidnode->pkt->pkt.user_id->len, 0);
     616             : 
     617           0 :                   if (uidnode->pkt->pkt.user_id->is_revoked)
     618             :                     {
     619           0 :                       tty_fprintf (fp, _("User ID \"%s\" is revoked."), user);
     620             : 
     621           0 :                       if (selfsig)
     622           0 :                         tty_fprintf (fp, "\n");
     623           0 :                       else if (opt.expert && !quick)
     624             :                         {
     625           0 :                           tty_fprintf (fp, "\n");
     626             :                           /* No, so remove the mark and continue */
     627           0 :                           if (!cpr_get_answer_is_yes ("sign_uid.revoke_okay",
     628           0 :                                                       _("Are you sure you "
     629             :                                                         "still want to sign "
     630             :                                                         "it? (y/N) ")))
     631             :                             {
     632           0 :                               uidnode->flag &= ~NODFLG_MARK_A;
     633           0 :                               uidnode = NULL;
     634             :                             }
     635           0 :                           else if (interactive)
     636           0 :                             yesreally = 1;
     637             :                         }
     638             :                       else
     639             :                         {
     640           0 :                           uidnode->flag &= ~NODFLG_MARK_A;
     641           0 :                           uidnode = NULL;
     642           0 :                           tty_fprintf (fp, _("  Unable to sign.\n"));
     643             :                         }
     644             :                     }
     645           0 :                   else if (uidnode->pkt->pkt.user_id->is_expired)
     646             :                     {
     647           0 :                       tty_fprintf (fp, _("User ID \"%s\" is expired."), user);
     648             : 
     649           0 :                       if (selfsig)
     650           0 :                         tty_fprintf (fp, "\n");
     651           0 :                       else if (opt.expert && !quick)
     652             :                         {
     653           0 :                           tty_fprintf (fp, "\n");
     654             :                           /* No, so remove the mark and continue */
     655           0 :                           if (!cpr_get_answer_is_yes ("sign_uid.expire_okay",
     656           0 :                                                       _("Are you sure you "
     657             :                                                         "still want to sign "
     658             :                                                         "it? (y/N) ")))
     659             :                             {
     660           0 :                               uidnode->flag &= ~NODFLG_MARK_A;
     661           0 :                               uidnode = NULL;
     662             :                             }
     663           0 :                           else if (interactive)
     664           0 :                             yesreally = 1;
     665             :                         }
     666             :                       else
     667             :                         {
     668           0 :                           uidnode->flag &= ~NODFLG_MARK_A;
     669           0 :                           uidnode = NULL;
     670           0 :                           tty_fprintf (fp, _("  Unable to sign.\n"));
     671             :                         }
     672             :                     }
     673           0 :                   else if (!uidnode->pkt->pkt.user_id->created && !selfsig)
     674             :                     {
     675           0 :                       tty_fprintf (fp, _("User ID \"%s\" is not self-signed."),
     676             :                                    user);
     677             : 
     678           0 :                       if (opt.expert && !quick)
     679             :                         {
     680           0 :                           tty_fprintf (fp, "\n");
     681             :                           /* No, so remove the mark and continue */
     682           0 :                           if (!cpr_get_answer_is_yes ("sign_uid.nosig_okay",
     683           0 :                                                       _("Are you sure you "
     684             :                                                         "still want to sign "
     685             :                                                         "it? (y/N) ")))
     686             :                             {
     687           0 :                               uidnode->flag &= ~NODFLG_MARK_A;
     688           0 :                               uidnode = NULL;
     689             :                             }
     690           0 :                           else if (interactive)
     691           0 :                             yesreally = 1;
     692             :                         }
     693             :                       else
     694             :                         {
     695           0 :                           uidnode->flag &= ~NODFLG_MARK_A;
     696           0 :                           uidnode = NULL;
     697           0 :                           tty_fprintf (fp, _("  Unable to sign.\n"));
     698             :                         }
     699             :                     }
     700             : 
     701           0 :                   if (uidnode && interactive && !yesreally && !quick)
     702             :                     {
     703           0 :                       tty_fprintf (fp,
     704           0 :                                    _("User ID \"%s\" is signable.  "), user);
     705           0 :                       if (!cpr_get_answer_is_yes ("sign_uid.sign_okay",
     706           0 :                                                   _("Sign it? (y/N) ")))
     707             :                         {
     708           0 :                           uidnode->flag &= ~NODFLG_MARK_A;
     709           0 :                           uidnode = NULL;
     710             :                         }
     711             :                     }
     712             : 
     713           0 :                   xfree (user);
     714             :                 }
     715             :             }
     716           0 :           else if (uidnode && node->pkt->pkttype == PKT_SIGNATURE
     717           0 :                    && (node->pkt->pkt.signature->sig_class & ~3) == 0x10)
     718             :             {
     719           0 :               if (sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
     720           0 :                   && sk_keyid[1] == node->pkt->pkt.signature->keyid[1])
     721             :                 {
     722             :                   char buf[50];
     723             :                   char *user;
     724             : 
     725           0 :                   user = utf8_to_native (uidnode->pkt->pkt.user_id->name,
     726           0 :                                          uidnode->pkt->pkt.user_id->len, 0);
     727             : 
     728             :                   /* It's a v3 self-sig.  Make it into a v4 self-sig? */
     729           0 :                   if (node->pkt->pkt.signature->version < 4
     730           0 :                       && selfsig && !quick)
     731             :                     {
     732           0 :                       tty_fprintf (fp,
     733           0 :                                    _("The self-signature on \"%s\"\n"
     734             :                                      "is a PGP 2.x-style signature.\n"), user);
     735             : 
     736             :                       /* Note that the regular PGP2 warning below
     737             :                          still applies if there are no v4 sigs on
     738             :                          this key at all. */
     739             : 
     740           0 :                       if (opt.expert)
     741           0 :                         if (cpr_get_answer_is_yes ("sign_uid.v4_promote_okay",
     742           0 :                                                    _("Do you want to promote "
     743             :                                                      "it to an OpenPGP self-"
     744             :                                                      "signature? (y/N) ")))
     745             :                           {
     746           0 :                             node->flag |= NODFLG_DELSIG;
     747           0 :                             xfree (user);
     748           0 :                             continue;
     749             :                           }
     750             :                     }
     751             : 
     752             :                   /* Is the current signature expired? */
     753           0 :                   if (node->pkt->pkt.signature->flags.expired)
     754             :                     {
     755           0 :                       tty_fprintf (fp, _("Your current signature on \"%s\"\n"
     756             :                                          "has expired.\n"), user);
     757             : 
     758           0 :                       if (quick || cpr_get_answer_is_yes
     759             :                           ("sign_uid.replace_expired_okay",
     760           0 :                            _("Do you want to issue a "
     761             :                              "new signature to replace "
     762             :                              "the expired one? (y/N) ")))
     763             :                         {
     764             :                           /* Mark these for later deletion.  We
     765             :                              don't want to delete them here, just in
     766             :                              case the replacement signature doesn't
     767             :                              happen for some reason.  We only delete
     768             :                              these after the replacement is already
     769             :                              in place. */
     770             : 
     771           0 :                           node->flag |= NODFLG_DELSIG;
     772           0 :                           xfree (user);
     773           0 :                           continue;
     774             :                         }
     775             :                     }
     776             : 
     777           0 :                   if (!node->pkt->pkt.signature->flags.exportable && !local)
     778             :                     {
     779             :                       /* It's a local sig, and we want to make a
     780             :                          exportable sig. */
     781           0 :                       tty_fprintf (fp, _("Your current signature on \"%s\"\n"
     782             :                                          "is a local signature.\n"), user);
     783             : 
     784           0 :                       if (quick || cpr_get_answer_is_yes
     785             :                           ("sign_uid.local_promote_okay",
     786           0 :                            _("Do you want to promote "
     787             :                              "it to a full exportable " "signature? (y/N) ")))
     788             :                         {
     789             :                           /* Mark these for later deletion.  We
     790             :                              don't want to delete them here, just in
     791             :                              case the replacement signature doesn't
     792             :                              happen for some reason.  We only delete
     793             :                              these after the replacement is already
     794             :                              in place. */
     795             : 
     796           0 :                           node->flag |= NODFLG_DELSIG;
     797           0 :                           xfree (user);
     798           0 :                           continue;
     799             :                         }
     800             :                     }
     801             : 
     802             :                   /* Fixme: see whether there is a revocation in which
     803             :                    * case we should allow to sign it again. */
     804           0 :                   if (!node->pkt->pkt.signature->flags.exportable && local)
     805           0 :                     tty_fprintf ( fp,
     806           0 :                        _("\"%s\" was already locally signed by key %s\n"),
     807             :                        user, keystr_from_pk (pk));
     808             :                   else
     809           0 :                     tty_fprintf (fp,
     810           0 :                                 _("\"%s\" was already signed by key %s\n"),
     811             :                                 user, keystr_from_pk (pk));
     812             : 
     813           0 :                   if (opt.expert && !quick
     814           0 :                       && cpr_get_answer_is_yes ("sign_uid.dupe_okay",
     815           0 :                                                 _("Do you want to sign it "
     816             :                                                   "again anyway? (y/N) ")))
     817             :                     {
     818             :                       /* Don't delete the old sig here since this is
     819             :                          an --expert thing. */
     820           0 :                       xfree (user);
     821           0 :                       continue;
     822             :                     }
     823             : 
     824           0 :                   snprintf (buf, sizeof buf, "%08lX%08lX",
     825           0 :                             (ulong) pk->keyid[0], (ulong) pk->keyid[1]);
     826           0 :                   write_status_text (STATUS_ALREADY_SIGNED, buf);
     827           0 :                   uidnode->flag &= ~NODFLG_MARK_A;       /* remove mark */
     828             : 
     829           0 :                   xfree (user);
     830             :                 }
     831             :             }
     832             :         }
     833             : 
     834             :       /* Check whether any uids are left for signing.  */
     835           0 :       if (!count_uids_with_flag (keyblock, NODFLG_MARK_A))
     836             :         {
     837           0 :           tty_fprintf (fp, _("Nothing to sign with key %s\n"),
     838             :                       keystr_from_pk (pk));
     839           0 :           continue;
     840             :         }
     841             : 
     842             :       /* Ask whether we really should sign these user id(s). */
     843           0 :       tty_fprintf (fp, "\n");
     844           0 :       show_key_with_all_names (ctrl, fp, keyblock, 1, 0, 1, 0, 0, 0);
     845           0 :       tty_fprintf (fp, "\n");
     846             : 
     847           0 :       if (primary_pk->expiredate && !selfsig)
     848             :         {
     849           0 :           u32 now = make_timestamp ();
     850             : 
     851           0 :           if (primary_pk->expiredate <= now)
     852             :             {
     853           0 :               tty_fprintf (fp, _("This key has expired!"));
     854             : 
     855           0 :               if (opt.expert && !quick)
     856             :                 {
     857           0 :                   tty_fprintf (fp, "  ");
     858           0 :                   if (!cpr_get_answer_is_yes ("sign_uid.expired_okay",
     859           0 :                                               _("Are you sure you still "
     860             :                                                 "want to sign it? (y/N) ")))
     861           0 :                     continue;
     862             :                 }
     863             :               else
     864             :                 {
     865           0 :                   tty_fprintf (fp, _("  Unable to sign.\n"));
     866           0 :                   continue;
     867             :                 }
     868             :             }
     869             :           else
     870             :             {
     871           0 :               tty_fprintf (fp, _("This key is due to expire on %s.\n"),
     872             :                            expirestr_from_pk (primary_pk));
     873             : 
     874           0 :               if (opt.ask_cert_expire && !quick)
     875             :                 {
     876           0 :                   char *answer = cpr_get ("sign_uid.expire",
     877           0 :                                           _("Do you want your signature to "
     878             :                                             "expire at the same time? (Y/n) "));
     879           0 :                   if (answer_is_yes_no_default (answer, 1))
     880             :                     {
     881             :                       /* This fixes the signature timestamp we're
     882             :                          going to make as now.  This is so the
     883             :                          expiration date is exactly correct, and not
     884             :                          a few seconds off (due to the time it takes
     885             :                          to answer the questions, enter the
     886             :                          passphrase, etc). */
     887           0 :                       timestamp = now;
     888           0 :                       duration = primary_pk->expiredate - now;
     889             :                     }
     890             : 
     891           0 :                   cpr_kill_prompt ();
     892           0 :                   xfree (answer);
     893             :                 }
     894             :             }
     895             :         }
     896             : 
     897             :       /* Only ask for duration if we haven't already set it to match
     898             :          the expiration of the pk */
     899           0 :       if (!duration && !selfsig)
     900             :         {
     901           0 :           if (opt.ask_cert_expire && !quick)
     902           0 :             duration = ask_expire_interval (1, opt.def_cert_expire);
     903             :           else
     904           0 :             duration = parse_expire_string (opt.def_cert_expire);
     905             :         }
     906             : 
     907           0 :       if (selfsig)
     908             :         ;
     909             :       else
     910             :         {
     911           0 :           if (opt.batch || !opt.ask_cert_level || quick)
     912           0 :             class = 0x10 + opt.def_cert_level;
     913             :           else
     914             :             {
     915             :               char *answer;
     916             : 
     917           0 :               tty_fprintf (fp,
     918           0 :                            _("How carefully have you verified the key you are "
     919             :                             "about to sign actually belongs\nto the person "
     920             :                             "named above?  If you don't know what to "
     921             :                             "answer, enter \"0\".\n"));
     922           0 :               tty_fprintf (fp, "\n");
     923           0 :               tty_fprintf (fp, _("   (0) I will not answer.%s\n"),
     924           0 :                           opt.def_cert_level == 0 ? " (default)" : "");
     925           0 :               tty_fprintf (fp, _("   (1) I have not checked at all.%s\n"),
     926           0 :                           opt.def_cert_level == 1 ? " (default)" : "");
     927           0 :               tty_fprintf (fp, _("   (2) I have done casual checking.%s\n"),
     928           0 :                           opt.def_cert_level == 2 ? " (default)" : "");
     929           0 :               tty_fprintf (fp,
     930           0 :                            _("   (3) I have done very careful checking.%s\n"),
     931           0 :                           opt.def_cert_level == 3 ? " (default)" : "");
     932           0 :               tty_fprintf (fp, "\n");
     933             : 
     934           0 :               while (class == 0)
     935             :                 {
     936           0 :                   answer = cpr_get ("sign_uid.class",
     937           0 :                                     _("Your selection? "
     938             :                                       "(enter '?' for more information): "));
     939           0 :                   if (answer[0] == '\0')
     940           0 :                     class = 0x10 + opt.def_cert_level;  /* Default */
     941           0 :                   else if (ascii_strcasecmp (answer, "0") == 0)
     942           0 :                     class = 0x10;       /* Generic */
     943           0 :                   else if (ascii_strcasecmp (answer, "1") == 0)
     944           0 :                     class = 0x11;       /* Persona */
     945           0 :                   else if (ascii_strcasecmp (answer, "2") == 0)
     946           0 :                     class = 0x12;       /* Casual */
     947           0 :                   else if (ascii_strcasecmp (answer, "3") == 0)
     948           0 :                     class = 0x13;       /* Positive */
     949             :                   else
     950           0 :                     tty_fprintf (fp, _("Invalid selection.\n"));
     951             : 
     952           0 :                   xfree (answer);
     953             :                 }
     954             :             }
     955             : 
     956           0 :           if (trust && !quick)
     957           0 :             trustsig_prompt (&trust_value, &trust_depth, &trust_regexp);
     958             :         }
     959             : 
     960           0 :       if (!quick)
     961             :         {
     962           0 :           p = get_user_id_native (sk_keyid);
     963           0 :           tty_fprintf (fp,
     964           0 :                    _("Are you sure that you want to sign this key with your\n"
     965             :                      "key \"%s\" (%s)\n"), p, keystr_from_pk (pk));
     966           0 :           xfree (p);
     967             :         }
     968             : 
     969           0 :       if (selfsig)
     970             :         {
     971           0 :           tty_fprintf (fp, "\n");
     972           0 :           tty_fprintf (fp, _("This will be a self-signature.\n"));
     973             : 
     974           0 :           if (local)
     975             :             {
     976           0 :               tty_fprintf (fp, "\n");
     977           0 :               tty_fprintf (fp, _("WARNING: the signature will not be marked "
     978             :                                  "as non-exportable.\n"));
     979             :             }
     980             : 
     981           0 :           if (nonrevocable)
     982             :             {
     983           0 :               tty_fprintf (fp, "\n");
     984           0 :               tty_fprintf (fp, _("WARNING: the signature will not be marked "
     985             :                                  "as non-revocable.\n"));
     986             :             }
     987             :         }
     988             :       else
     989             :         {
     990           0 :           if (local)
     991             :             {
     992           0 :               tty_fprintf (fp, "\n");
     993           0 :               tty_fprintf (fp,
     994           0 :                  _("The signature will be marked as non-exportable.\n"));
     995             :             }
     996             : 
     997           0 :           if (nonrevocable)
     998             :             {
     999           0 :               tty_fprintf (fp, "\n");
    1000           0 :               tty_fprintf (fp,
    1001           0 :                  _("The signature will be marked as non-revocable.\n"));
    1002             :             }
    1003             : 
    1004           0 :           switch (class)
    1005             :             {
    1006             :             case 0x11:
    1007           0 :               tty_fprintf (fp, "\n");
    1008           0 :               tty_fprintf (fp, _("I have not checked this key at all.\n"));
    1009           0 :               break;
    1010             : 
    1011             :             case 0x12:
    1012           0 :               tty_fprintf (fp, "\n");
    1013           0 :               tty_fprintf (fp, _("I have checked this key casually.\n"));
    1014           0 :               break;
    1015             : 
    1016             :             case 0x13:
    1017           0 :               tty_fprintf (fp, "\n");
    1018           0 :               tty_fprintf (fp, _("I have checked this key very carefully.\n"));
    1019           0 :               break;
    1020             :             }
    1021             :         }
    1022             : 
    1023           0 :       tty_fprintf (fp, "\n");
    1024             : 
    1025           0 :       if (opt.batch && opt.answer_yes)
    1026             :         ;
    1027           0 :       else if (quick)
    1028             :         ;
    1029           0 :       else if (!cpr_get_answer_is_yes ("sign_uid.okay",
    1030           0 :                                        _("Really sign? (y/N) ")))
    1031           0 :         continue;
    1032             : 
    1033             :       /* Now we can sign the user ids.  */
    1034             :     reloop:  /* (Must use this, because we are modifing the list.)  */
    1035           0 :       primary_pk = NULL;
    1036           0 :       for (node = keyblock; node; node = node->next)
    1037             :         {
    1038           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    1039           0 :             primary_pk = node->pkt->pkt.public_key;
    1040           0 :           else if (node->pkt->pkttype == PKT_USER_ID
    1041           0 :                    && (node->flag & NODFLG_MARK_A))
    1042             :             {
    1043             :               PACKET *pkt;
    1044             :               PKT_signature *sig;
    1045             :               struct sign_attrib attrib;
    1046             : 
    1047           0 :               assert (primary_pk);
    1048           0 :               memset (&attrib, 0, sizeof attrib);
    1049           0 :               attrib.non_exportable = local;
    1050           0 :               attrib.non_revocable = nonrevocable;
    1051           0 :               attrib.trust_depth = trust_depth;
    1052           0 :               attrib.trust_value = trust_value;
    1053           0 :               attrib.trust_regexp = trust_regexp;
    1054           0 :               node->flag &= ~NODFLG_MARK_A;
    1055             : 
    1056             :               /* We force creation of a v4 signature for local
    1057             :                * signatures, otherwise we would not generate the
    1058             :                * subpacket with v3 keys and the signature becomes
    1059             :                * exportable.  */
    1060             : 
    1061           0 :               if (selfsig)
    1062           0 :                 rc = make_keysig_packet (&sig, primary_pk,
    1063           0 :                                          node->pkt->pkt.user_id,
    1064             :                                          NULL,
    1065             :                                          pk,
    1066             :                                          0x13, 0, 0, 0,
    1067             :                                          keygen_add_std_prefs, primary_pk,
    1068             :                                          NULL);
    1069             :               else
    1070           0 :                 rc = make_keysig_packet (&sig, primary_pk,
    1071           0 :                                          node->pkt->pkt.user_id,
    1072             :                                          NULL,
    1073             :                                          pk,
    1074             :                                          class, 0,
    1075             :                                          timestamp, duration,
    1076             :                                          sign_mk_attrib, &attrib,
    1077             :                                          NULL);
    1078           0 :               if (rc)
    1079             :                 {
    1080           0 :                   write_status_error ("keysig", rc);
    1081           0 :                   log_error (_("signing failed: %s\n"), gpg_strerror (rc));
    1082           0 :                   goto leave;
    1083             :                 }
    1084             : 
    1085           0 :               *ret_modified = 1;        /* We changed the keyblock. */
    1086           0 :               update_trust = 1;
    1087             : 
    1088           0 :               pkt = xmalloc_clear (sizeof *pkt);
    1089           0 :               pkt->pkttype = PKT_SIGNATURE;
    1090           0 :               pkt->pkt.signature = sig;
    1091           0 :               insert_kbnode (node, new_kbnode (pkt), PKT_SIGNATURE);
    1092           0 :               goto reloop;
    1093             :             }
    1094             :         }
    1095             : 
    1096             :       /* Delete any sigs that got promoted */
    1097           0 :       for (node = keyblock; node; node = node->next)
    1098           0 :         if (node->flag & NODFLG_DELSIG)
    1099           0 :           delete_kbnode (node);
    1100             :     } /* End loop over signators.  */
    1101             : 
    1102             :  leave:
    1103           0 :   release_sk_list (sk_list);
    1104           0 :   return rc;
    1105             : }
    1106             : 
    1107             : 
    1108             : /*
    1109             :  * Change the passphrase of the primary and all secondary keys.  Note
    1110             :  * that it is common to use only one passphrase for the primary and
    1111             :  * all subkeys.  However, this is now (since GnuPG 2.1) all up to the
    1112             :  * gpg-agent.  Returns 0 on success or an error code.
    1113             :  */
    1114             : static gpg_error_t
    1115           0 : change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
    1116             : {
    1117             :   gpg_error_t err;
    1118             :   kbnode_t node;
    1119             :   PKT_public_key *pk;
    1120             :   int any;
    1121             :   u32 keyid[2], subid[2];
    1122           0 :   char *hexgrip = NULL;
    1123           0 :   char *cache_nonce = NULL;
    1124           0 :   char *passwd_nonce = NULL;
    1125             : 
    1126           0 :   node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
    1127           0 :   if (!node)
    1128             :     {
    1129           0 :       log_error ("Oops; public key missing!\n");
    1130           0 :       err = gpg_error (GPG_ERR_INTERNAL);
    1131           0 :       goto leave;
    1132             :     }
    1133           0 :   pk = node->pkt->pkt.public_key;
    1134           0 :   keyid_from_pk (pk, keyid);
    1135             : 
    1136             :   /* Check whether it is likely that we will be able to change the
    1137             :      passphrase for any subkey.  */
    1138           0 :   for (any = 0, node = keyblock; node; node = node->next)
    1139             :     {
    1140           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    1141           0 :           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1142             :         {
    1143             :           char *serialno;
    1144             : 
    1145           0 :           pk = node->pkt->pkt.public_key;
    1146           0 :           keyid_from_pk (pk, subid);
    1147             : 
    1148           0 :           xfree (hexgrip);
    1149           0 :           err = hexkeygrip_from_pk (pk, &hexgrip);
    1150           0 :           if (err)
    1151           0 :             goto leave;
    1152           0 :           err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
    1153           0 :           if (!err && serialno)
    1154             :             ; /* Key on card.  */
    1155           0 :           else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
    1156             :             ; /* Maybe stub key. */
    1157           0 :           else if (!err)
    1158           0 :             any = 1; /* Key is known.  */
    1159             :           else
    1160           0 :             log_error ("key %s: error getting keyinfo from agent: %s\n",
    1161             :                        keystr_with_sub (keyid, subid), gpg_strerror (err));
    1162           0 :           xfree (serialno);
    1163             :         }
    1164             :     }
    1165           0 :   err = 0;
    1166           0 :   if (!any)
    1167             :     {
    1168           0 :       tty_printf (_("Key has only stub or on-card key items - "
    1169             :                     "no passphrase to change.\n"));
    1170           0 :       goto leave;
    1171             :     }
    1172             : 
    1173             :   /* Change the passphrase for all keys.  */
    1174           0 :   for (any = 0, node = keyblock; node; node = node->next)
    1175             :     {
    1176           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    1177           0 :           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    1178             :         {
    1179             :           char *desc;
    1180             : 
    1181           0 :           pk = node->pkt->pkt.public_key;
    1182           0 :           keyid_from_pk (pk, subid);
    1183             : 
    1184           0 :           xfree (hexgrip);
    1185           0 :           err = hexkeygrip_from_pk (pk, &hexgrip);
    1186           0 :           if (err)
    1187           0 :             goto leave;
    1188             : 
    1189           0 :           desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1);
    1190           0 :           err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
    1191           0 :           xfree (desc);
    1192             : 
    1193           0 :           if (err)
    1194           0 :             log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
    1195           0 :                       || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
    1196             :                      ? GPGRT_LOG_INFO : GPGRT_LOG_ERROR,
    1197           0 :                      _("key %s: error changing passphrase: %s\n"),
    1198             :                        keystr_with_sub (keyid, subid),
    1199             :                        gpg_strerror (err));
    1200           0 :           if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
    1201           0 :             break;
    1202             :         }
    1203             :     }
    1204             : 
    1205             :  leave:
    1206           0 :   xfree (hexgrip);
    1207           0 :   xfree (cache_nonce);
    1208           0 :   xfree (passwd_nonce);
    1209           0 :   return err;
    1210             : }
    1211             : 
    1212             : 
    1213             : 
    1214             : /*
    1215             :  * There are some keys out (due to a bug in gnupg), where the sequence
    1216             :  * of the packets is wrong.  This function fixes that.
    1217             :  * Returns: true if the keyblock has been fixed.
    1218             :  *
    1219             :  * Note:  This function does not work if there is more than one user ID.
    1220             :  */
    1221             : static int
    1222           0 : fix_key_signature_order (KBNODE keyblock)
    1223             : {
    1224             :   KBNODE node, last, subkey;
    1225           0 :   int fixed = 0;
    1226             : 
    1227             :   /* Locate key signatures of class 0x10..0x13 behind sub key packets.  */
    1228           0 :   for (subkey = last = NULL, node = keyblock; node;
    1229           0 :        last = node, node = node->next)
    1230             :     {
    1231           0 :       switch (node->pkt->pkttype)
    1232             :         {
    1233             :         case PKT_PUBLIC_SUBKEY:
    1234             :         case PKT_SECRET_SUBKEY:
    1235           0 :           if (!subkey)
    1236           0 :             subkey = last; /* Actually it is the one before the subkey.  */
    1237           0 :           break;
    1238             :         case PKT_SIGNATURE:
    1239           0 :           if (subkey)
    1240             :             {
    1241           0 :               PKT_signature *sig = node->pkt->pkt.signature;
    1242           0 :               if (sig->sig_class >= 0x10 && sig->sig_class <= 0x13)
    1243             :                 {
    1244           0 :                   log_info (_("moving a key signature to the correct place\n"));
    1245           0 :                   last->next = node->next;
    1246           0 :                   node->next = subkey->next;
    1247           0 :                   subkey->next = node;
    1248           0 :                   node = last;
    1249           0 :                   fixed = 1;
    1250             :                 }
    1251             :             }
    1252           0 :           break;
    1253             :         default:
    1254           0 :           break;
    1255             :         }
    1256             :     }
    1257             : 
    1258           0 :   return fixed;
    1259             : }
    1260             : 
    1261             : 
    1262             : /* Fix various problems in the keyblock.  Returns true if the keyblock
    1263             :    was changed.  Note that a pointer to the keyblock must be given and
    1264             :    the function may change it (i.e. replacing the first node).  */
    1265             : static int
    1266           0 : fix_keyblock (kbnode_t *keyblockp)
    1267             : {
    1268           0 :   int changed = 0;
    1269             : 
    1270           0 :   if (fix_key_signature_order (*keyblockp))
    1271           0 :     changed++;
    1272           0 :   if (collapse_uids (keyblockp))
    1273           0 :     changed++;
    1274           0 :   reorder_keyblock (*keyblockp);
    1275             :   /* If we modified the keyblock, make sure the flags are right. */
    1276           0 :   if (changed)
    1277           0 :     merge_keys_and_selfsig (*keyblockp);
    1278             : 
    1279           0 :   return changed;
    1280             : }
    1281             : 
    1282             : 
    1283             : static int
    1284           0 : parse_sign_type (const char *str, int *localsig, int *nonrevokesig,
    1285             :                  int *trustsig)
    1286             : {
    1287           0 :   const char *p = str;
    1288             : 
    1289           0 :   while (*p)
    1290             :     {
    1291           0 :       if (ascii_strncasecmp (p, "l", 1) == 0)
    1292             :         {
    1293           0 :           *localsig = 1;
    1294           0 :           p++;
    1295             :         }
    1296           0 :       else if (ascii_strncasecmp (p, "nr", 2) == 0)
    1297             :         {
    1298           0 :           *nonrevokesig = 1;
    1299           0 :           p += 2;
    1300             :         }
    1301           0 :       else if (ascii_strncasecmp (p, "t", 1) == 0)
    1302             :         {
    1303           0 :           *trustsig = 1;
    1304           0 :           p++;
    1305             :         }
    1306             :       else
    1307           0 :         return 0;
    1308             :     }
    1309             : 
    1310           0 :   return 1;
    1311             : }
    1312             : 
    1313             : 
    1314             : 
    1315             : /*
    1316             :  * Menu driven key editor.  If seckey_check is true, then a secret key
    1317             :  * that matches username will be looked for.  If it is false, not all
    1318             :  * commands will be available.
    1319             :  *
    1320             :  * Note: to keep track of certain selections we use node->mark MARKBIT_xxxx.
    1321             :  */
    1322             : 
    1323             : /* Need an SK for this command */
    1324             : #define KEYEDIT_NEED_SK 1
    1325             : /* Cannot be viewing the SK for this command */
    1326             : #define KEYEDIT_NOT_SK  2
    1327             : /* Must be viewing the SK for this command */
    1328             : #define KEYEDIT_ONLY_SK 4
    1329             : /* Match the tail of the string */
    1330             : #define KEYEDIT_TAIL_MATCH 8
    1331             : 
    1332             : enum cmdids
    1333             : {
    1334             :   cmdNONE = 0,
    1335             :   cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
    1336             :   cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
    1337             :   cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
    1338             :   cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
    1339             :   cmdEXPIRE, cmdBACKSIGN,
    1340             : #ifndef NO_TRUST_MODELS
    1341             :   cmdENABLEKEY, cmdDISABLEKEY,
    1342             : #endif /*!NO_TRUST_MODELS*/
    1343             :   cmdSHOWPREF,
    1344             :   cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
    1345             :   cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCHECKBKUPKEY,
    1346             :   cmdCLEAN, cmdMINIMIZE, cmdGRIP, cmdNOP
    1347             : };
    1348             : 
    1349             : static struct
    1350             : {
    1351             :   const char *name;
    1352             :   enum cmdids id;
    1353             :   int flags;
    1354             :   const char *desc;
    1355             : } cmds[] =
    1356             : {
    1357             :   { "quit", cmdQUIT, 0, N_("quit this menu")},
    1358             :   { "q", cmdQUIT, 0, NULL},
    1359             :   { "save", cmdSAVE, 0, N_("save and quit")},
    1360             :   { "help", cmdHELP, 0, N_("show this help")},
    1361             :   { "?", cmdHELP, 0, NULL},
    1362             :   { "fpr", cmdFPR, 0, N_("show key fingerprint")},
    1363             :   { "grip", cmdGRIP, 0, N_("show the keygrip")},
    1364             :   { "list", cmdLIST, 0, N_("list key and user IDs")},
    1365             :   { "l", cmdLIST, 0, NULL},
    1366             :   { "uid", cmdSELUID, 0, N_("select user ID N")},
    1367             :   { "key", cmdSELKEY, 0, N_("select subkey N")},
    1368             :   { "check", cmdCHECK, 0, N_("check signatures")},
    1369             :   { "c", cmdCHECK, 0, NULL},
    1370             :   { "cross-certify", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
    1371             :   { "backsign", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
    1372             :   { "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH,
    1373             :     N_("sign selected user IDs [* see below for related commands]")},
    1374             :   { "s", cmdSIGN, KEYEDIT_NOT_SK, NULL},
    1375             :     /* "lsign" and friends will never match since "sign" comes first
    1376             :        and it is a tail match.  They are just here so they show up in
    1377             :        the help menu. */
    1378             :   { "lsign", cmdNOP, 0, N_("sign selected user IDs locally")},
    1379             :   { "tsign", cmdNOP, 0, N_("sign selected user IDs with a trust signature")},
    1380             :   { "nrsign", cmdNOP, 0,
    1381             :     N_("sign selected user IDs with a non-revocable signature")},
    1382             :   { "debug", cmdDEBUG, 0, NULL},
    1383             :   { "adduid", cmdADDUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a user ID")},
    1384             :   { "addphoto", cmdADDPHOTO, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1385             :     N_("add a photo ID")},
    1386             :   { "deluid", cmdDELUID, KEYEDIT_NOT_SK, N_("delete selected user IDs")},
    1387             :     /* delphoto is really deluid in disguise */
    1388             :   { "delphoto", cmdDELUID, KEYEDIT_NOT_SK, NULL},
    1389             :   { "addkey", cmdADDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a subkey")},
    1390             : #ifdef ENABLE_CARD_SUPPORT
    1391             :   { "addcardkey", cmdADDCARDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1392             :     N_("add a key to a smartcard")},
    1393             :   { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK,
    1394             :     N_("move a key to a smartcard")},
    1395             :   { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK,
    1396             :     N_("move a backup key to a smartcard")},
    1397             :   { "checkbkupkey", cmdCHECKBKUPKEY, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK, NULL},
    1398             : #endif /*ENABLE_CARD_SUPPORT */
    1399             :   { "delkey", cmdDELKEY, KEYEDIT_NOT_SK, N_("delete selected subkeys")},
    1400             :   { "addrevoker", cmdADDREVOKER, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1401             :     N_("add a revocation key")},
    1402             :   { "delsig", cmdDELSIG, KEYEDIT_NOT_SK,
    1403             :     N_("delete signatures from the selected user IDs")},
    1404             :   { "expire", cmdEXPIRE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1405             :     N_("change the expiration date for the key or selected subkeys")},
    1406             :   { "primary", cmdPRIMARY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1407             :     N_("flag the selected user ID as primary")},
    1408             :   { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},  /* Dummy command.  */
    1409             :   { "t", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},
    1410             :   { "pref", cmdPREF, KEYEDIT_NOT_SK, N_("list preferences (expert)")},
    1411             :   { "showpref", cmdSHOWPREF, KEYEDIT_NOT_SK, N_("list preferences (verbose)")},
    1412             :   { "setpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1413             :     N_("set preference list for the selected user IDs")},
    1414             :   { "updpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
    1415             :   { "keyserver", cmdPREFKS, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1416             :     N_("set the preferred keyserver URL for the selected user IDs")},
    1417             :   { "notation", cmdNOTATION, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1418             :     N_("set a notation for the selected user IDs")},
    1419             :   { "passwd", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1420             :     N_("change the passphrase")},
    1421             :   { "password", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
    1422             : #ifndef NO_TRUST_MODELS
    1423             :   { "trust", cmdTRUST, KEYEDIT_NOT_SK, N_("change the ownertrust")},
    1424             : #endif /*!NO_TRUST_MODELS*/
    1425             :   { "revsig", cmdREVSIG, KEYEDIT_NOT_SK,
    1426             :     N_("revoke signatures on the selected user IDs")},
    1427             :   { "revuid", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1428             :     N_("revoke selected user IDs")},
    1429             :   { "revphoto", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
    1430             :   { "revkey", cmdREVKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
    1431             :     N_("revoke key or selected subkeys")},
    1432             : #ifndef NO_TRUST_MODELS
    1433             :   { "enable", cmdENABLEKEY, KEYEDIT_NOT_SK, N_("enable key")},
    1434             :   { "disable", cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key")},
    1435             : #endif /*!NO_TRUST_MODELS*/
    1436             :   { "showphoto", cmdSHOWPHOTO, 0, N_("show selected photo IDs")},
    1437             :   { "clean", cmdCLEAN, KEYEDIT_NOT_SK,
    1438             :     N_("compact unusable user IDs and remove unusable signatures from key")},
    1439             :   { "minimize", cmdMINIMIZE, KEYEDIT_NOT_SK,
    1440             :     N_("compact unusable user IDs and remove all signatures from key")},
    1441             : 
    1442             :   { NULL, cmdNONE, 0, NULL}
    1443             : };
    1444             : 
    1445             : 
    1446             : 
    1447             : #ifdef HAVE_LIBREADLINE
    1448             : 
    1449             : /*
    1450             :    These two functions are used by readline for command completion.
    1451             :  */
    1452             : 
    1453             : static char *
    1454             : command_generator (const char *text, int state)
    1455             : {
    1456             :   static int list_index, len;
    1457             :   const char *name;
    1458             : 
    1459             :   /* If this is a new word to complete, initialize now.  This includes
    1460             :      saving the length of TEXT for efficiency, and initializing the
    1461             :      index variable to 0. */
    1462             :   if (!state)
    1463             :     {
    1464             :       list_index = 0;
    1465             :       len = strlen (text);
    1466             :     }
    1467             : 
    1468             :   /* Return the next partial match */
    1469             :   while ((name = cmds[list_index].name))
    1470             :     {
    1471             :       /* Only complete commands that have help text */
    1472             :       if (cmds[list_index++].desc && strncmp (name, text, len) == 0)
    1473             :         return strdup (name);
    1474             :     }
    1475             : 
    1476             :   return NULL;
    1477             : }
    1478             : 
    1479             : static char **
    1480             : keyedit_completion (const char *text, int start, int end)
    1481             : {
    1482             :   /* If we are at the start of a line, we try and command-complete.
    1483             :      If not, just do nothing for now. */
    1484             : 
    1485             :   (void) end;
    1486             : 
    1487             :   if (start == 0)
    1488             :     return rl_completion_matches (text, command_generator);
    1489             : 
    1490             :   rl_attempted_completion_over = 1;
    1491             : 
    1492             :   return NULL;
    1493             : }
    1494             : #endif /* HAVE_LIBREADLINE */
    1495             : 
    1496             : 
    1497             : 
    1498             : /* Main function of the menu driven key editor.  */
    1499             : void
    1500           0 : keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
    1501             :               strlist_t commands, int quiet, int seckey_check)
    1502             : {
    1503           0 :   enum cmdids cmd = 0;
    1504           0 :   gpg_error_t err = 0;
    1505           0 :   KBNODE keyblock = NULL;
    1506           0 :   KEYDB_HANDLE kdbhd = NULL;
    1507           0 :   int have_seckey = 0;
    1508           0 :   char *answer = NULL;
    1509           0 :   int redisplay = 1;
    1510           0 :   int modified = 0;
    1511           0 :   int sec_shadowing = 0;
    1512           0 :   int run_subkey_warnings = 0;
    1513           0 :   int have_commands = !!commands;
    1514             : 
    1515           0 :   if (opt.command_fd != -1)
    1516             :     ;
    1517           0 :   else if (opt.batch && !have_commands)
    1518             :     {
    1519           0 :       log_error (_("can't do this in batch mode\n"));
    1520           0 :       goto leave;
    1521             :     }
    1522             : 
    1523             : #ifdef HAVE_W32_SYSTEM
    1524             :   /* Due to Windows peculiarities we need to make sure that the
    1525             :      trustdb stale check is done before we open another file
    1526             :      (i.e. by searching for a key).  In theory we could make sure
    1527             :      that the files are closed after use but the open/close caches
    1528             :      inhibits that and flushing the cache right before the stale
    1529             :      check is not easy to implement.  Thus we take the easy way out
    1530             :      and run the stale check as early as possible.  Note, that for
    1531             :      non- W32 platforms it is run indirectly trough a call to
    1532             :      get_validity ().  */
    1533             :   check_trustdb_stale ();
    1534             : #endif
    1535             : 
    1536             :   /* Get the public key */
    1537           0 :   err = get_pubkey_byname (ctrl, NULL, NULL, username, &keyblock, &kdbhd, 1, 1);
    1538           0 :   if (err)
    1539             :     {
    1540           0 :       log_error (_("key \"%s\" not found: %s\n"), username, gpg_strerror (err));
    1541           0 :       goto leave;
    1542             :     }
    1543             : 
    1544           0 :   if (fix_keyblock (&keyblock))
    1545           0 :     modified++;
    1546             : 
    1547             :   /* See whether we have a matching secret key.  */
    1548           0 :   if (seckey_check)
    1549             :     {
    1550           0 :       have_seckey = !agent_probe_any_secret_key (ctrl, keyblock);
    1551           0 :       if (have_seckey && !quiet)
    1552           0 :         tty_printf (_("Secret key is available.\n"));
    1553             :     }
    1554             : 
    1555             :   /* Main command loop.  */
    1556             :   for (;;)
    1557             :     {
    1558             :       int i, arg_number, photo;
    1559           0 :       const char *arg_string = "";
    1560             :       char *p;
    1561           0 :       PKT_public_key *pk = keyblock->pkt->pkt.public_key;
    1562             : 
    1563           0 :       tty_printf ("\n");
    1564             : 
    1565           0 :       if (redisplay && !quiet)
    1566             :         {
    1567             :           /* Show using flags: with_revoker, with_subkeys.  */
    1568           0 :           show_key_with_all_names (ctrl, NULL, keyblock, 0, 1, 0, 1, 0, 0);
    1569           0 :           tty_printf ("\n");
    1570           0 :           redisplay = 0;
    1571             :         }
    1572             : 
    1573           0 :       if (run_subkey_warnings)
    1574             :         {
    1575           0 :           run_subkey_warnings = 0;
    1576           0 :           if (!count_selected_keys (keyblock))
    1577           0 :             subkey_expire_warning (keyblock);
    1578             :         }
    1579             : 
    1580             :       do
    1581             :         {
    1582           0 :           xfree (answer);
    1583           0 :           if (have_commands)
    1584             :             {
    1585           0 :               if (commands)
    1586             :                 {
    1587           0 :                   answer = xstrdup (commands->d);
    1588           0 :                   commands = commands->next;
    1589             :                 }
    1590           0 :               else if (opt.batch)
    1591             :                 {
    1592           0 :                   answer = xstrdup ("quit");
    1593             :                 }
    1594             :               else
    1595           0 :                 have_commands = 0;
    1596             :             }
    1597           0 :           if (!have_commands)
    1598             :             {
    1599             : #ifdef HAVE_LIBREADLINE
    1600             :               tty_enable_completion (keyedit_completion);
    1601             : #endif
    1602           0 :               answer = cpr_get_no_help ("keyedit.prompt", GPG_NAME "> ");
    1603           0 :               cpr_kill_prompt ();
    1604             :               tty_disable_completion ();
    1605             :             }
    1606           0 :           trim_spaces (answer);
    1607             :         }
    1608           0 :       while (*answer == '#');
    1609             : 
    1610           0 :       arg_number = 0; /* Here is the init which egcc complains about.  */
    1611           0 :       photo = 0;      /* Same here. */
    1612           0 :       if (!*answer)
    1613           0 :         cmd = cmdLIST;
    1614           0 :       else if (*answer == CONTROL_D)
    1615           0 :         cmd = cmdQUIT;
    1616           0 :       else if (digitp (answer))
    1617             :         {
    1618           0 :           cmd = cmdSELUID;
    1619           0 :           arg_number = atoi (answer);
    1620             :         }
    1621             :       else
    1622             :         {
    1623           0 :           if ((p = strchr (answer, ' ')))
    1624             :             {
    1625           0 :               *p++ = 0;
    1626           0 :               trim_spaces (answer);
    1627           0 :               trim_spaces (p);
    1628           0 :               arg_number = atoi (p);
    1629           0 :               arg_string = p;
    1630             :             }
    1631             : 
    1632           0 :           for (i = 0; cmds[i].name; i++)
    1633             :             {
    1634           0 :               if (cmds[i].flags & KEYEDIT_TAIL_MATCH)
    1635             :                 {
    1636           0 :                   size_t l = strlen (cmds[i].name);
    1637           0 :                   size_t a = strlen (answer);
    1638           0 :                   if (a >= l)
    1639             :                     {
    1640           0 :                       if (!ascii_strcasecmp (&answer[a - l], cmds[i].name))
    1641             :                         {
    1642           0 :                           answer[a - l] = '\0';
    1643           0 :                           break;
    1644             :                         }
    1645             :                     }
    1646             :                 }
    1647           0 :               else if (!ascii_strcasecmp (answer, cmds[i].name))
    1648           0 :                 break;
    1649             :             }
    1650           0 :           if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey)
    1651             :             {
    1652           0 :               tty_printf (_("Need the secret key to do this.\n"));
    1653           0 :               cmd = cmdNOP;
    1654             :             }
    1655             :           else
    1656           0 :             cmd = cmds[i].id;
    1657             :         }
    1658             : 
    1659             :       /* Dispatch the command.  */
    1660           0 :       switch (cmd)
    1661             :         {
    1662             :         case cmdHELP:
    1663           0 :           for (i = 0; cmds[i].name; i++)
    1664             :             {
    1665           0 :               if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey)
    1666             :                 ; /* Skip those item if we do not have the secret key.  */
    1667           0 :               else if (cmds[i].desc)
    1668           0 :                 tty_printf ("%-11s %s\n", cmds[i].name, _(cmds[i].desc));
    1669             :             }
    1670             : 
    1671           0 :           tty_printf ("\n");
    1672           0 :           tty_printf
    1673           0 :             (_("* The 'sign' command may be prefixed with an 'l' for local "
    1674             :                "signatures (lsign),\n"
    1675             :                "  a 't' for trust signatures (tsign), an 'nr' for "
    1676             :                "non-revocable signatures\n"
    1677             :                "  (nrsign), or any combination thereof (ltsign, "
    1678             :                "tnrsign, etc.).\n"));
    1679           0 :           break;
    1680             : 
    1681             :         case cmdLIST:
    1682           0 :           redisplay = 1;
    1683           0 :           break;
    1684             : 
    1685             :         case cmdFPR:
    1686           0 :           show_key_and_fingerprint
    1687           0 :             (keyblock, (*arg_string == '*'
    1688           0 :                         && (!arg_string[1] || spacep (arg_string + 1))));
    1689           0 :           break;
    1690             : 
    1691             :         case cmdGRIP:
    1692           0 :           show_key_and_grip (keyblock);
    1693           0 :           break;
    1694             : 
    1695             :         case cmdSELUID:
    1696           0 :           if (strlen (arg_string) == NAMEHASH_LEN * 2)
    1697           0 :             redisplay = menu_select_uid_namehash (keyblock, arg_string);
    1698             :           else
    1699             :             {
    1700           0 :               if (*arg_string == '*'
    1701           0 :                   && (!arg_string[1] || spacep (arg_string + 1)))
    1702           0 :                 arg_number = -1;        /* Select all. */
    1703           0 :               redisplay = menu_select_uid (keyblock, arg_number);
    1704             :             }
    1705           0 :           break;
    1706             : 
    1707             :         case cmdSELKEY:
    1708             :           {
    1709           0 :             if (*arg_string == '*'
    1710           0 :                 && (!arg_string[1] || spacep (arg_string + 1)))
    1711           0 :               arg_number = -1;  /* Select all. */
    1712           0 :             if (menu_select_key (keyblock, arg_number))
    1713           0 :               redisplay = 1;
    1714             :           }
    1715           0 :           break;
    1716             : 
    1717             :         case cmdCHECK:
    1718           0 :           check_all_keysigs (keyblock, count_selected_uids (keyblock),
    1719           0 :                              !strcmp (arg_string, "selfsig"));
    1720           0 :           break;
    1721             : 
    1722             :         case cmdSIGN:
    1723             :           {
    1724           0 :             int localsig = 0, nonrevokesig = 0, trustsig = 0, interactive = 0;
    1725             : 
    1726           0 :             if (pk->flags.revoked)
    1727             :               {
    1728           0 :                 tty_printf (_("Key is revoked."));
    1729             : 
    1730           0 :                 if (opt.expert)
    1731             :                   {
    1732           0 :                     tty_printf ("  ");
    1733           0 :                     if (!cpr_get_answer_is_yes
    1734             :                         ("keyedit.sign_revoked.okay",
    1735           0 :                          _("Are you sure you still want to sign it? (y/N) ")))
    1736           0 :                       break;
    1737             :                   }
    1738             :                 else
    1739             :                   {
    1740           0 :                     tty_printf (_("  Unable to sign.\n"));
    1741           0 :                     break;
    1742             :                   }
    1743             :               }
    1744             : 
    1745           0 :             if (count_uids (keyblock) > 1 && !count_selected_uids (keyblock)
    1746           0 :                 && !cpr_get_answer_is_yes ("keyedit.sign_all.okay",
    1747           0 :                                            _("Really sign all user IDs?"
    1748             :                                              " (y/N) ")))
    1749             :               {
    1750           0 :                 if (opt.interactive)
    1751           0 :                   interactive = 1;
    1752             :                 else
    1753             :                   {
    1754           0 :                     tty_printf (_("Hint: Select the user IDs to sign\n"));
    1755           0 :                     have_commands = 0;
    1756           0 :                     break;
    1757             :                   }
    1758             : 
    1759             :               }
    1760             :             /* What sort of signing are we doing? */
    1761           0 :             if (!parse_sign_type
    1762             :                 (answer, &localsig, &nonrevokesig, &trustsig))
    1763             :               {
    1764           0 :                 tty_printf (_("Unknown signature type '%s'\n"), answer);
    1765           0 :                 break;
    1766             :               }
    1767             : 
    1768           0 :             sign_uids (ctrl, NULL, keyblock, locusr, &modified,
    1769             :                        localsig, nonrevokesig, trustsig, interactive, 0);
    1770             :           }
    1771           0 :           break;
    1772             : 
    1773             :         case cmdDEBUG:
    1774           0 :           dump_kbnode (keyblock);
    1775           0 :           break;
    1776             : 
    1777             :         case cmdTOGGLE:
    1778             :           /* The toggle command is a leftover from old gpg versions
    1779             :              where we worked with a secret and a public keyring.  It
    1780             :              is not necessary anymore but we keep this command for the
    1781             :              sake of scripts using it.  */
    1782           0 :           redisplay = 1;
    1783           0 :           break;
    1784             : 
    1785             :         case cmdADDPHOTO:
    1786           0 :           if (RFC2440)
    1787             :             {
    1788           0 :               tty_printf (_("This command is not allowed while in %s mode.\n"),
    1789             :                           compliance_option_string ());
    1790           0 :               break;
    1791             :             }
    1792           0 :           photo = 1;
    1793             :           /* fall through */
    1794             :         case cmdADDUID:
    1795           0 :           if (menu_adduid (keyblock, photo, arg_string, NULL))
    1796             :             {
    1797           0 :               update_trust = 1;
    1798           0 :               redisplay = 1;
    1799           0 :               modified = 1;
    1800           0 :               merge_keys_and_selfsig (keyblock);
    1801             :             }
    1802           0 :           break;
    1803             : 
    1804             :         case cmdDELUID:
    1805             :           {
    1806             :             int n1;
    1807             : 
    1808           0 :             if (!(n1 = count_selected_uids (keyblock)))
    1809             :               {
    1810           0 :                 tty_printf (_("You must select at least one user ID.\n"));
    1811           0 :                 if (!opt.expert)
    1812           0 :                   tty_printf (_("(Use the '%s' command.)\n"), "uid");
    1813             :               }
    1814           0 :             else if (real_uids_left (keyblock) < 1)
    1815           0 :               tty_printf (_("You can't delete the last user ID!\n"));
    1816           0 :             else if (cpr_get_answer_is_yes
    1817             :                      ("keyedit.remove.uid.okay",
    1818             :                       n1 > 1 ? _("Really remove all selected user IDs? (y/N) ")
    1819             :                       :        _("Really remove this user ID? (y/N) ")))
    1820             :               {
    1821           0 :                 menu_deluid (keyblock);
    1822           0 :                 redisplay = 1;
    1823           0 :                 modified = 1;
    1824             :               }
    1825             :           }
    1826           0 :           break;
    1827             : 
    1828             :         case cmdDELSIG:
    1829             :           {
    1830             :             int n1;
    1831             : 
    1832           0 :             if (!(n1 = count_selected_uids (keyblock)))
    1833             :               {
    1834           0 :                 tty_printf (_("You must select at least one user ID.\n"));
    1835           0 :                 if (!opt.expert)
    1836           0 :                   tty_printf (_("(Use the '%s' command.)\n"), "uid");
    1837             :               }
    1838           0 :             else if (menu_delsig (keyblock))
    1839             :               {
    1840             :                 /* No redisplay here, because it may scroll away some
    1841             :                  * of the status output of this command.  */
    1842           0 :                 modified = 1;
    1843             :               }
    1844             :           }
    1845           0 :           break;
    1846             : 
    1847             :         case cmdADDKEY:
    1848           0 :           if (!generate_subkeypair (ctrl, keyblock))
    1849             :             {
    1850           0 :               redisplay = 1;
    1851           0 :               modified = 1;
    1852           0 :               merge_keys_and_selfsig (keyblock);
    1853             :             }
    1854           0 :           break;
    1855             : 
    1856             : #ifdef ENABLE_CARD_SUPPORT
    1857             :         case cmdADDCARDKEY:
    1858           0 :           if (!card_generate_subkey (keyblock))
    1859             :             {
    1860           0 :               redisplay = 1;
    1861           0 :               modified = 1;
    1862           0 :               merge_keys_and_selfsig (keyblock);
    1863             :             }
    1864           0 :           break;
    1865             : 
    1866             :         case cmdKEYTOCARD:
    1867             :           {
    1868           0 :             KBNODE node = NULL;
    1869           0 :             switch (count_selected_keys (keyblock))
    1870             :               {
    1871             :               case 0:
    1872           0 :                 if (cpr_get_answer_is_yes
    1873             :                     ("keyedit.keytocard.use_primary",
    1874             :                      /* TRANSLATORS: Please take care: This is about
    1875             :                         moving the key and not about removing it.  */
    1876           0 :                      _("Really move the primary key? (y/N) ")))
    1877           0 :                   node = keyblock;
    1878           0 :                 break;
    1879             :               case 1:
    1880           0 :                 for (node = keyblock; node; node = node->next)
    1881             :                   {
    1882           0 :                     if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    1883           0 :                         && node->flag & NODFLG_SELKEY)
    1884           0 :                       break;
    1885             :                   }
    1886           0 :                 break;
    1887             :               default:
    1888           0 :                 tty_printf (_("You must select exactly one key.\n"));
    1889           0 :                 break;
    1890             :               }
    1891           0 :             if (node)
    1892             :               {
    1893           0 :                 PKT_public_key *xxpk = node->pkt->pkt.public_key;
    1894           0 :                 if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0))
    1895             :                   {
    1896           0 :                     redisplay = 1;
    1897           0 :                     sec_shadowing = 1;
    1898             :                   }
    1899             :               }
    1900             :           }
    1901           0 :           break;
    1902             : 
    1903             :         case cmdBKUPTOCARD:
    1904             :         case cmdCHECKBKUPKEY:
    1905           0 :           log_debug ("FIXME: This needs to be changed\n");
    1906             :           {
    1907             :             /* Ask for a filename, check whether this is really a
    1908             :                backup key as generated by the card generation, parse
    1909             :                that key and store it on card. */
    1910             :             KBNODE node;
    1911             :             const char *fname;
    1912             :             PACKET *pkt;
    1913             :             IOBUF a;
    1914             : 
    1915           0 :             fname = arg_string;
    1916           0 :             if (!*fname)
    1917             :               {
    1918           0 :                 tty_printf (_("Command expects a filename argument\n"));
    1919           0 :                 break;
    1920             :               }
    1921             : 
    1922             :             /* Open that file.  */
    1923           0 :             a = iobuf_open (fname);
    1924           0 :             if (a && is_secured_file (iobuf_get_fd (a)))
    1925             :               {
    1926           0 :                 iobuf_close (a);
    1927           0 :                 a = NULL;
    1928           0 :                 gpg_err_set_errno (EPERM);
    1929             :               }
    1930           0 :             if (!a)
    1931             :               {
    1932           0 :                 tty_printf (_("Can't open '%s': %s\n"),
    1933           0 :                             fname, strerror (errno));
    1934           0 :                 break;
    1935             :               }
    1936             : 
    1937             :             /* Parse and check that file.  */
    1938           0 :             pkt = xmalloc (sizeof *pkt);
    1939           0 :             init_packet (pkt);
    1940           0 :             err = parse_packet (a, pkt);
    1941           0 :             iobuf_close (a);
    1942           0 :             iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
    1943           0 :             if (!err && pkt->pkttype != PKT_SECRET_KEY
    1944           0 :                 && pkt->pkttype != PKT_SECRET_SUBKEY)
    1945           0 :               err = GPG_ERR_NO_SECKEY;
    1946           0 :             if (err)
    1947             :               {
    1948           0 :                 tty_printf (_("Error reading backup key from '%s': %s\n"),
    1949             :                             fname, gpg_strerror (err));
    1950           0 :                 free_packet (pkt);
    1951           0 :                 xfree (pkt);
    1952           0 :                 break;
    1953             :               }
    1954           0 :             node = new_kbnode (pkt);
    1955             : 
    1956           0 :             if (cmd == cmdCHECKBKUPKEY)
    1957             :               {
    1958             :                 /* PKT_public_key *sk = node->pkt->pkt.secret_key; */
    1959             :                 /* switch (is_secret_key_protected (sk)) */
    1960             :                 /*   { */
    1961             :                 /*   case 0:    /\* Not protected. *\/ */
    1962             :                 /*     tty_printf (_("This key is not protected.\n")); */
    1963             :                 /*     break; */
    1964             :                 /*   case -1: */
    1965             :                 /*     log_error (_("unknown key protection algorithm\n")); */
    1966             :                 /*     break; */
    1967             :                 /*   default: */
    1968             :                 /*     if (sk->protect.s2k.mode == 1001) */
    1969             :                 /*       tty_printf (_("Secret parts of key" */
    1970             :                 /*                  " are not available.\n")); */
    1971             :                 /*     if (sk->protect.s2k.mode == 1002) */
    1972             :                 /*       tty_printf (_("Secret parts of key" */
    1973             :                 /*                  " are stored on-card.\n")); */
    1974             :                     /* else */
    1975             :                     /*   check_secret_key (sk, 0); */
    1976             :                   /* } */
    1977             :               }
    1978             :             else                /* Store it.  */
    1979             :               {
    1980           0 :                 if (card_store_subkey (node, 0))
    1981             :                   {
    1982           0 :                     redisplay = 1;
    1983           0 :                     sec_shadowing = 1;
    1984             :                   }
    1985             :               }
    1986           0 :             release_kbnode (node);
    1987             :           }
    1988           0 :           break;
    1989             : 
    1990             : #endif /* ENABLE_CARD_SUPPORT */
    1991             : 
    1992             :         case cmdDELKEY:
    1993             :           {
    1994             :             int n1;
    1995             : 
    1996           0 :             if (!(n1 = count_selected_keys (keyblock)))
    1997             :               {
    1998           0 :                 tty_printf (_("You must select at least one key.\n"));
    1999           0 :                 if (!opt.expert)
    2000           0 :                   tty_printf (_("(Use the '%s' command.)\n"), "key");
    2001             :               }
    2002           0 :             else if (!cpr_get_answer_is_yes
    2003             :                      ("keyedit.remove.subkey.okay",
    2004             :                       n1 > 1 ? _("Do you really want to delete the "
    2005             :                                  "selected keys? (y/N) ")
    2006             :                       :  _("Do you really want to delete this key? (y/N) ")))
    2007             :               ;
    2008             :             else
    2009             :               {
    2010           0 :                 menu_delkey (keyblock);
    2011           0 :                 redisplay = 1;
    2012           0 :                 modified = 1;
    2013             :               }
    2014             :           }
    2015           0 :           break;
    2016             : 
    2017             :         case cmdADDREVOKER:
    2018             :           {
    2019           0 :             int sensitive = 0;
    2020             : 
    2021           0 :             if (ascii_strcasecmp (arg_string, "sensitive") == 0)
    2022           0 :               sensitive = 1;
    2023           0 :             if (menu_addrevoker (ctrl, keyblock, sensitive))
    2024             :               {
    2025           0 :                 redisplay = 1;
    2026           0 :                 modified = 1;
    2027           0 :                 merge_keys_and_selfsig (keyblock);
    2028             :               }
    2029             :           }
    2030           0 :           break;
    2031             : 
    2032             :         case cmdREVUID:
    2033             :           {
    2034             :             int n1;
    2035             : 
    2036           0 :             if (!(n1 = count_selected_uids (keyblock)))
    2037             :               {
    2038           0 :                 tty_printf (_("You must select at least one user ID.\n"));
    2039           0 :                 if (!opt.expert)
    2040           0 :                   tty_printf (_("(Use the '%s' command.)\n"), "uid");
    2041             :               }
    2042           0 :             else if (cpr_get_answer_is_yes
    2043             :                      ("keyedit.revoke.uid.okay",
    2044             :                       n1 > 1 ? _("Really revoke all selected user IDs? (y/N) ")
    2045             :                       :        _("Really revoke this user ID? (y/N) ")))
    2046             :               {
    2047           0 :                 if (menu_revuid (keyblock))
    2048             :                   {
    2049           0 :                     modified = 1;
    2050           0 :                     redisplay = 1;
    2051             :                   }
    2052             :               }
    2053             :           }
    2054           0 :           break;
    2055             : 
    2056             :         case cmdREVKEY:
    2057             :           {
    2058             :             int n1;
    2059             : 
    2060           0 :             if (!(n1 = count_selected_keys (keyblock)))
    2061             :               {
    2062           0 :                 if (cpr_get_answer_is_yes ("keyedit.revoke.subkey.okay",
    2063           0 :                                            _("Do you really want to revoke"
    2064             :                                              " the entire key? (y/N) ")))
    2065             :                   {
    2066           0 :                     if (menu_revkey (keyblock))
    2067           0 :                       modified = 1;
    2068             : 
    2069           0 :                     redisplay = 1;
    2070             :                   }
    2071             :               }
    2072           0 :             else if (cpr_get_answer_is_yes ("keyedit.revoke.subkey.okay",
    2073             :                                             n1 > 1 ?
    2074             :                                             _("Do you really want to revoke"
    2075             :                                               " the selected subkeys? (y/N) ")
    2076             :                                             : _("Do you really want to revoke"
    2077             :                                                 " this subkey? (y/N) ")))
    2078             :               {
    2079           0 :                 if (menu_revsubkey (keyblock))
    2080           0 :                   modified = 1;
    2081             : 
    2082           0 :                 redisplay = 1;
    2083             :               }
    2084             : 
    2085           0 :             if (modified)
    2086           0 :               merge_keys_and_selfsig (keyblock);
    2087             :           }
    2088           0 :           break;
    2089             : 
    2090             :         case cmdEXPIRE:
    2091           0 :           if (menu_expire (keyblock))
    2092             :             {
    2093           0 :               merge_keys_and_selfsig (keyblock);
    2094           0 :               run_subkey_warnings = 1;
    2095           0 :               modified = 1;
    2096           0 :               redisplay = 1;
    2097             :             }
    2098           0 :           break;
    2099             : 
    2100             :         case cmdBACKSIGN:
    2101           0 :           if (menu_backsign (keyblock))
    2102             :             {
    2103           0 :               modified = 1;
    2104           0 :               redisplay = 1;
    2105             :             }
    2106           0 :           break;
    2107             : 
    2108             :         case cmdPRIMARY:
    2109           0 :           if (menu_set_primary_uid (keyblock))
    2110             :             {
    2111           0 :               merge_keys_and_selfsig (keyblock);
    2112           0 :               modified = 1;
    2113           0 :               redisplay = 1;
    2114             :             }
    2115           0 :           break;
    2116             : 
    2117             :         case cmdPASSWD:
    2118           0 :           change_passphrase (ctrl, keyblock);
    2119           0 :           break;
    2120             : 
    2121             : #ifndef NO_TRUST_MODELS
    2122             :         case cmdTRUST:
    2123           0 :           if (opt.trust_model == TM_EXTERNAL)
    2124             :             {
    2125           0 :               tty_printf (_("Owner trust may not be set while "
    2126             :                             "using a user provided trust database\n"));
    2127           0 :               break;
    2128             :             }
    2129             : 
    2130           0 :           show_key_with_all_names (ctrl, NULL, keyblock, 0, 0, 0, 1, 0, 0);
    2131           0 :           tty_printf ("\n");
    2132           0 :           if (edit_ownertrust (find_kbnode (keyblock,
    2133           0 :                                             PKT_PUBLIC_KEY)->pkt->pkt.
    2134             :                                public_key, 1))
    2135             :             {
    2136           0 :               redisplay = 1;
    2137             :               /* No real need to set update_trust here as
    2138             :                  edit_ownertrust() calls revalidation_mark()
    2139             :                  anyway. */
    2140           0 :               update_trust = 1;
    2141             :             }
    2142           0 :           break;
    2143             : #endif /*!NO_TRUST_MODELS*/
    2144             : 
    2145             :         case cmdPREF:
    2146             :           {
    2147           0 :             int count = count_selected_uids (keyblock);
    2148           0 :             assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
    2149           0 :             show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
    2150             :                         count ? NODFLG_SELUID : 0, 1);
    2151             :           }
    2152           0 :           break;
    2153             : 
    2154             :         case cmdSHOWPREF:
    2155             :           {
    2156           0 :             int count = count_selected_uids (keyblock);
    2157           0 :             assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
    2158           0 :             show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
    2159             :                         count ? NODFLG_SELUID : 0, 2);
    2160             :           }
    2161           0 :           break;
    2162             : 
    2163             :         case cmdSETPREF:
    2164             :           {
    2165             :             PKT_user_id *tempuid;
    2166             : 
    2167           0 :             keygen_set_std_prefs (!*arg_string ? "default" : arg_string, 0);
    2168             : 
    2169           0 :             tempuid = keygen_get_std_prefs ();
    2170           0 :             tty_printf (_("Set preference list to:\n"));
    2171           0 :             show_prefs (tempuid, NULL, 1);
    2172           0 :             free_user_id (tempuid);
    2173             : 
    2174           0 :             if (cpr_get_answer_is_yes
    2175             :                 ("keyedit.setpref.okay",
    2176           0 :                  count_selected_uids (keyblock) ?
    2177             :                  _("Really update the preferences"
    2178             :                    " for the selected user IDs? (y/N) ")
    2179             :                  : _("Really update the preferences? (y/N) ")))
    2180             :               {
    2181           0 :                 if (menu_set_preferences (keyblock))
    2182             :                   {
    2183           0 :                     merge_keys_and_selfsig (keyblock);
    2184           0 :                     modified = 1;
    2185           0 :                     redisplay = 1;
    2186             :                   }
    2187             :               }
    2188             :           }
    2189           0 :           break;
    2190             : 
    2191             :         case cmdPREFKS:
    2192           0 :           if (menu_set_keyserver_url (*arg_string ? arg_string : NULL,
    2193             :                                       keyblock))
    2194             :             {
    2195           0 :               merge_keys_and_selfsig (keyblock);
    2196           0 :               modified = 1;
    2197           0 :               redisplay = 1;
    2198             :             }
    2199           0 :           break;
    2200             : 
    2201             :         case cmdNOTATION:
    2202           0 :           if (menu_set_notation (*arg_string ? arg_string : NULL,
    2203             :                                  keyblock))
    2204             :             {
    2205           0 :               merge_keys_and_selfsig (keyblock);
    2206           0 :               modified = 1;
    2207           0 :               redisplay = 1;
    2208             :             }
    2209           0 :           break;
    2210             : 
    2211             :         case cmdNOP:
    2212           0 :           break;
    2213             : 
    2214             :         case cmdREVSIG:
    2215           0 :           if (menu_revsig (keyblock))
    2216             :             {
    2217           0 :               redisplay = 1;
    2218           0 :               modified = 1;
    2219             :             }
    2220           0 :           break;
    2221             : 
    2222             : #ifndef NO_TRUST_MODELS
    2223             :         case cmdENABLEKEY:
    2224             :         case cmdDISABLEKEY:
    2225           0 :           if (enable_disable_key (keyblock, cmd == cmdDISABLEKEY))
    2226             :             {
    2227           0 :               redisplay = 1;
    2228           0 :               modified = 1;
    2229             :             }
    2230           0 :           break;
    2231             : #endif /*!NO_TRUST_MODELS*/
    2232             : 
    2233             :         case cmdSHOWPHOTO:
    2234           0 :           menu_showphoto (keyblock);
    2235           0 :           break;
    2236             : 
    2237             :         case cmdCLEAN:
    2238           0 :           if (menu_clean (keyblock, 0))
    2239           0 :             redisplay = modified = 1;
    2240           0 :           break;
    2241             : 
    2242             :         case cmdMINIMIZE:
    2243           0 :           if (menu_clean (keyblock, 1))
    2244           0 :             redisplay = modified = 1;
    2245           0 :           break;
    2246             : 
    2247             :         case cmdQUIT:
    2248           0 :           if (have_commands)
    2249           0 :             goto leave;
    2250           0 :           if (!modified && !sec_shadowing)
    2251           0 :             goto leave;
    2252           0 :           if (!cpr_get_answer_is_yes ("keyedit.save.okay",
    2253           0 :                                       _("Save changes? (y/N) ")))
    2254             :             {
    2255           0 :               if (cpr_enabled ()
    2256           0 :                   || cpr_get_answer_is_yes ("keyedit.cancel.okay",
    2257           0 :                                             _("Quit without saving? (y/N) ")))
    2258             :                 goto leave;
    2259           0 :               break;
    2260             :             }
    2261             :           /* fall thru */
    2262             :         case cmdSAVE:
    2263           0 :           if (modified)
    2264             :             {
    2265           0 :               err = keydb_update_keyblock (kdbhd, keyblock);
    2266           0 :               if (err)
    2267             :                 {
    2268           0 :                   log_error (_("update failed: %s\n"), gpg_strerror (err));
    2269           0 :                   break;
    2270             :                 }
    2271             :             }
    2272             : 
    2273           0 :           if (sec_shadowing)
    2274             :             {
    2275           0 :               err = agent_scd_learn (NULL, 1);
    2276           0 :               if (err)
    2277             :                 {
    2278           0 :                   log_error (_("update failed: %s\n"), gpg_strerror (err));
    2279           0 :                   break;
    2280             :                 }
    2281             :             }
    2282             : 
    2283           0 :           if (!modified && !sec_shadowing)
    2284           0 :             tty_printf (_("Key not changed so no update needed.\n"));
    2285             : 
    2286           0 :           if (update_trust)
    2287             :             {
    2288           0 :               revalidation_mark ();
    2289           0 :               update_trust = 0;
    2290             :             }
    2291           0 :           goto leave;
    2292             : 
    2293             :         case cmdINVCMD:
    2294             :         default:
    2295           0 :           tty_printf ("\n");
    2296           0 :           tty_printf (_("Invalid command  (try \"help\")\n"));
    2297           0 :           break;
    2298             :         }
    2299           0 :     } /* End of the main command loop.  */
    2300             : 
    2301             :  leave:
    2302           0 :   release_kbnode (keyblock);
    2303           0 :   keydb_release (kdbhd);
    2304           0 :   xfree (answer);
    2305           0 : }
    2306             : 
    2307             : 
    2308             : /* Change the passphrase of the secret key identified by USERNAME.  */
    2309             : void
    2310           0 : keyedit_passwd (ctrl_t ctrl, const char *username)
    2311             : {
    2312             :   gpg_error_t err;
    2313             :   PKT_public_key *pk;
    2314           0 :   kbnode_t keyblock = NULL;
    2315             : 
    2316           0 :   pk = xtrycalloc (1, sizeof *pk);
    2317           0 :   if (!pk)
    2318             :     {
    2319           0 :       err = gpg_error_from_syserror ();
    2320           0 :       goto leave;
    2321             :     }
    2322           0 :   err = getkey_byname (ctrl, NULL, pk, username, 1, &keyblock);
    2323           0 :   if (err)
    2324           0 :     goto leave;
    2325             : 
    2326           0 :   err = change_passphrase (ctrl, keyblock);
    2327             : 
    2328             : leave:
    2329           0 :   release_kbnode (keyblock);
    2330           0 :   free_public_key (pk);
    2331           0 :   if (err)
    2332             :     {
    2333           0 :       log_info ("error changing the passphrase for '%s': %s\n",
    2334             :                 username, gpg_strerror (err));
    2335           0 :       write_status_error ("keyedit.passwd", err);
    2336             :     }
    2337             :   else
    2338           0 :     write_status_text (STATUS_SUCCESS, "keyedit.passwd");
    2339           0 : }
    2340             : 
    2341             : 
    2342             : /* Unattended adding of a new keyid.  USERNAME specifies the
    2343             :    key. NEWUID is the new user id to add to the key.  */
    2344             : void
    2345           0 : keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
    2346             : {
    2347             :   gpg_error_t err;
    2348           0 :   KEYDB_HANDLE kdbhd = NULL;
    2349             :   KEYDB_SEARCH_DESC desc;
    2350           0 :   kbnode_t keyblock = NULL;
    2351             :   kbnode_t node;
    2352           0 :   char *uidstring = NULL;
    2353             : 
    2354           0 :   uidstring = xstrdup (newuid);
    2355           0 :   trim_spaces (uidstring);
    2356           0 :   if (!*uidstring)
    2357             :     {
    2358           0 :       log_error ("%s\n", gpg_strerror (GPG_ERR_INV_USER_ID));
    2359           0 :       goto leave;
    2360             :     }
    2361             : 
    2362             : #ifdef HAVE_W32_SYSTEM
    2363             :   /* See keyedit_menu for why we need this.  */
    2364             :   check_trustdb_stale ();
    2365             : #endif
    2366             : 
    2367             :   /* Search the key; we don't want the whole getkey stuff here.  */
    2368           0 :   kdbhd = keydb_new ();
    2369           0 :   err = classify_user_id (username, &desc, 1);
    2370           0 :   if (!err)
    2371           0 :     err = keydb_search (kdbhd, &desc, 1, NULL);
    2372           0 :   if (!err)
    2373             :     {
    2374           0 :       err = keydb_get_keyblock (kdbhd, &keyblock);
    2375           0 :       if (err)
    2376             :         {
    2377           0 :           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
    2378           0 :           goto leave;
    2379             :         }
    2380             :       /* Now with the keyblock retrieved, search again to detect an
    2381             :          ambiguous specification.  We need to save the found state so
    2382             :          that we can do an update later.  */
    2383           0 :       keydb_push_found_state (kdbhd);
    2384           0 :       err = keydb_search (kdbhd, &desc, 1, NULL);
    2385           0 :       if (!err)
    2386           0 :         err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
    2387           0 :       else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
    2388           0 :         err = 0;
    2389           0 :       keydb_pop_found_state (kdbhd);
    2390             : 
    2391           0 :       if (!err)
    2392             :         {
    2393             :           /* We require the secret primary key to add a UID.  */
    2394           0 :           node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
    2395           0 :           if (!node)
    2396           0 :             BUG ();
    2397           0 :           err = agent_probe_secret_key (ctrl, node->pkt->pkt.public_key);
    2398             :         }
    2399             :     }
    2400           0 :   if (err)
    2401             :     {
    2402           0 :       log_error (_("secret key \"%s\" not found: %s\n"),
    2403             :                  username, gpg_strerror (err));
    2404           0 :       goto leave;
    2405             :     }
    2406             : 
    2407           0 :   fix_keyblock (&keyblock);
    2408             : 
    2409           0 :   if (menu_adduid (keyblock, 0, NULL, uidstring))
    2410             :     {
    2411           0 :       err = keydb_update_keyblock (kdbhd, keyblock);
    2412           0 :       if (err)
    2413             :         {
    2414           0 :           log_error (_("update failed: %s\n"), gpg_strerror (err));
    2415           0 :           goto leave;
    2416             :         }
    2417             : 
    2418           0 :       if (update_trust)
    2419           0 :         revalidation_mark ();
    2420             :     }
    2421             : 
    2422             :  leave:
    2423           0 :   xfree (uidstring);
    2424           0 :   release_kbnode (keyblock);
    2425           0 :   keydb_release (kdbhd);
    2426           0 : }
    2427             : 
    2428             : 
    2429             : /* Unattended key signing function.  If the key specifified by FPR is
    2430             :    availabale and FPR is the primary fingerprint all user ids of the
    2431             :    user ids of the key are signed using the default signing key.  If
    2432             :    UIDS is an empty list all usable UIDs are signed, if it is not
    2433             :    empty, only those user ids matching one of the entries of the loist
    2434             :    are signed.  With LOCAL being true kthe signatures are marked as
    2435             :    non-exportable.  */
    2436             : void
    2437           0 : keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
    2438             :                     strlist_t locusr, int local)
    2439             : {
    2440             :   gpg_error_t err;
    2441           0 :   kbnode_t keyblock = NULL;
    2442           0 :   KEYDB_HANDLE kdbhd = NULL;
    2443           0 :   int modified = 0;
    2444             :   KEYDB_SEARCH_DESC desc;
    2445             :   PKT_public_key *pk;
    2446             :   kbnode_t node;
    2447             :   strlist_t sl;
    2448             :   int any;
    2449             : 
    2450             : #ifdef HAVE_W32_SYSTEM
    2451             :   /* See keyedit_menu for why we need this.  */
    2452             :   check_trustdb_stale ();
    2453             : #endif
    2454             : 
    2455             :   /* We require a fingerprint because only this uniquely identifies a
    2456             :      key and may thus be used to select a key for unattended key
    2457             :      signing.  */
    2458           0 :   if (classify_user_id (fpr, &desc, 1)
    2459           0 :       || !(desc.mode == KEYDB_SEARCH_MODE_FPR
    2460           0 :            || desc.mode == KEYDB_SEARCH_MODE_FPR16
    2461           0 :            || desc.mode == KEYDB_SEARCH_MODE_FPR20))
    2462             :     {
    2463           0 :       log_error (_("\"%s\" is not a fingerprint\n"), fpr);
    2464           0 :       goto leave;
    2465             :     }
    2466           0 :   err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
    2467           0 :   if (err)
    2468             :     {
    2469           0 :       log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
    2470           0 :       goto leave;
    2471             :     }
    2472             : 
    2473             :   /* Check that the primary fingerprint has been given. */
    2474             :   {
    2475             :     byte fprbin[MAX_FINGERPRINT_LEN];
    2476             :     size_t fprlen;
    2477             : 
    2478           0 :     fingerprint_from_pk (keyblock->pkt->pkt.public_key, fprbin, &fprlen);
    2479           0 :     if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR16
    2480           0 :         && !memcmp (fprbin, desc.u.fpr, 16))
    2481             :       ;
    2482           0 :     else if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR
    2483           0 :              && !memcmp (fprbin, desc.u.fpr, 16)
    2484           0 :              && !desc.u.fpr[16]
    2485           0 :              && !desc.u.fpr[17]
    2486           0 :              && !desc.u.fpr[18]
    2487           0 :              && !desc.u.fpr[19])
    2488             :       ;
    2489           0 :     else if (fprlen == 20 && (desc.mode == KEYDB_SEARCH_MODE_FPR20
    2490           0 :                               || desc.mode == KEYDB_SEARCH_MODE_FPR)
    2491           0 :              && !memcmp (fprbin, desc.u.fpr, 20))
    2492             :       ;
    2493             :     else
    2494             :       {
    2495           0 :         log_error (_("\"%s\" is not the primary fingerprint\n"), fpr);
    2496           0 :         goto leave;
    2497             :       }
    2498             :   }
    2499             : 
    2500           0 :   if (fix_keyblock (&keyblock))
    2501           0 :     modified++;
    2502             : 
    2503             :   /* Give some info in verbose.  */
    2504           0 :   if (opt.verbose)
    2505             :     {
    2506           0 :       show_key_with_all_names (ctrl, es_stdout, keyblock, 0,
    2507             :                                1/*with_revoker*/, 1/*with_fingerprint*/,
    2508             :                                0, 0, 1);
    2509           0 :       es_fflush (es_stdout);
    2510             :     }
    2511             : 
    2512           0 :   pk = keyblock->pkt->pkt.public_key;
    2513           0 :   if (pk->flags.revoked)
    2514             :     {
    2515           0 :       if (!opt.verbose)
    2516           0 :         show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
    2517           0 :       log_error ("%s%s", _("Key is revoked."), _("  Unable to sign.\n"));
    2518           0 :       goto leave;
    2519             :     }
    2520             : 
    2521             :   /* Set the flags according to the UIDS list.  Fixme: We may want to
    2522             :      use classify_user_id along with dedicated compare functions so
    2523             :      that we match the same way as in the key lookup. */
    2524           0 :   any = 0;
    2525           0 :   menu_select_uid (keyblock, 0);   /* Better clear the flags first. */
    2526           0 :   for (sl=uids; sl; sl = sl->next)
    2527             :     {
    2528           0 :       for (node = keyblock; node; node = node->next)
    2529             :         {
    2530           0 :           if (node->pkt->pkttype == PKT_USER_ID)
    2531             :             {
    2532           0 :               PKT_user_id *uid = node->pkt->pkt.user_id;
    2533             : 
    2534           0 :               if (!uid->attrib_data
    2535           0 :                   && ascii_memistr (uid->name, uid->len, sl->d))
    2536             :                 {
    2537           0 :                   node->flag |= NODFLG_SELUID;
    2538           0 :                   any = 1;
    2539             :                 }
    2540             :             }
    2541             :         }
    2542             :     }
    2543             : 
    2544           0 :   if (uids && !any)
    2545             :     {
    2546           0 :       if (!opt.verbose)
    2547           0 :         show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
    2548           0 :       es_fflush (es_stdout);
    2549           0 :       log_error ("%s  %s", _("No matching user IDs."), _("Nothing to sign.\n"));
    2550           0 :       goto leave;
    2551             :     }
    2552             : 
    2553             :   /* Sign. */
    2554           0 :   sign_uids (ctrl, es_stdout, keyblock, locusr, &modified, local, 0, 0, 0, 1);
    2555           0 :   es_fflush (es_stdout);
    2556             : 
    2557           0 :   if (modified)
    2558             :     {
    2559           0 :       err = keydb_update_keyblock (kdbhd, keyblock);
    2560           0 :       if (err)
    2561             :         {
    2562           0 :           log_error (_("update failed: %s\n"), gpg_strerror (err));
    2563           0 :           goto leave;
    2564             :         }
    2565             :     }
    2566             :   else
    2567           0 :     log_info (_("Key not changed so no update needed.\n"));
    2568             : 
    2569           0 :   if (update_trust)
    2570           0 :     revalidation_mark ();
    2571             : 
    2572             : 
    2573             :  leave:
    2574           0 :   release_kbnode (keyblock);
    2575           0 :   keydb_release (kdbhd);
    2576           0 : }
    2577             : 
    2578             : 
    2579             : 
    2580             : static void
    2581           0 : tty_print_notations (int indent, PKT_signature * sig)
    2582             : {
    2583           0 :   int first = 1;
    2584             :   struct notation *notation, *nd;
    2585             : 
    2586           0 :   if (indent < 0)
    2587             :     {
    2588           0 :       first = 0;
    2589           0 :       indent = -indent;
    2590             :     }
    2591             : 
    2592           0 :   notation = sig_to_notation (sig);
    2593             : 
    2594           0 :   for (nd = notation; nd; nd = nd->next)
    2595             :     {
    2596           0 :       if (!first)
    2597           0 :         tty_printf ("%*s", indent, "");
    2598             :       else
    2599           0 :         first = 0;
    2600             : 
    2601           0 :       tty_print_utf8_string (nd->name, strlen (nd->name));
    2602           0 :       tty_printf ("=");
    2603           0 :       tty_print_utf8_string (nd->value, strlen (nd->value));
    2604           0 :       tty_printf ("\n");
    2605             :     }
    2606             : 
    2607           0 :   free_notation (notation);
    2608           0 : }
    2609             : 
    2610             : 
    2611             : /*
    2612             :  * Show preferences of a public keyblock.
    2613             :  */
    2614             : static void
    2615           0 : show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
    2616             : {
    2617           0 :   const prefitem_t fake = { 0, 0 };
    2618             :   const prefitem_t *prefs;
    2619             :   int i;
    2620             : 
    2621           0 :   if (!uid)
    2622           0 :     return;
    2623             : 
    2624           0 :   if (uid->prefs)
    2625           0 :     prefs = uid->prefs;
    2626           0 :   else if (verbose)
    2627           0 :     prefs = &fake;
    2628             :   else
    2629           0 :     return;
    2630             : 
    2631           0 :   if (verbose)
    2632             :     {
    2633           0 :       int any, des_seen = 0, sha1_seen = 0, uncomp_seen = 0;
    2634             : 
    2635           0 :       tty_printf ("     ");
    2636           0 :       tty_printf (_("Cipher: "));
    2637           0 :       for (i = any = 0; prefs[i].type; i++)
    2638             :         {
    2639           0 :           if (prefs[i].type == PREFTYPE_SYM)
    2640             :             {
    2641           0 :               if (any)
    2642           0 :                 tty_printf (", ");
    2643           0 :               any = 1;
    2644             :               /* We don't want to display strings for experimental algos */
    2645           0 :               if (!openpgp_cipher_test_algo (prefs[i].value)
    2646           0 :                   && prefs[i].value < 100)
    2647           0 :                 tty_printf ("%s", openpgp_cipher_algo_name (prefs[i].value));
    2648             :               else
    2649           0 :                 tty_printf ("[%d]", prefs[i].value);
    2650           0 :               if (prefs[i].value == CIPHER_ALGO_3DES)
    2651           0 :                 des_seen = 1;
    2652             :             }
    2653             :         }
    2654           0 :       if (!des_seen)
    2655             :         {
    2656           0 :           if (any)
    2657           0 :             tty_printf (", ");
    2658           0 :           tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
    2659             :         }
    2660           0 :       tty_printf ("\n     ");
    2661           0 :       tty_printf (_("Digest: "));
    2662           0 :       for (i = any = 0; prefs[i].type; i++)
    2663             :         {
    2664           0 :           if (prefs[i].type == PREFTYPE_HASH)
    2665             :             {
    2666           0 :               if (any)
    2667           0 :                 tty_printf (", ");
    2668           0 :               any = 1;
    2669             :               /* We don't want to display strings for experimental algos */
    2670           0 :               if (!gcry_md_test_algo (prefs[i].value) && prefs[i].value < 100)
    2671           0 :                 tty_printf ("%s", gcry_md_algo_name (prefs[i].value));
    2672             :               else
    2673           0 :                 tty_printf ("[%d]", prefs[i].value);
    2674           0 :               if (prefs[i].value == DIGEST_ALGO_SHA1)
    2675           0 :                 sha1_seen = 1;
    2676             :             }
    2677             :         }
    2678           0 :       if (!sha1_seen)
    2679             :         {
    2680           0 :           if (any)
    2681           0 :             tty_printf (", ");
    2682           0 :           tty_printf ("%s", gcry_md_algo_name (DIGEST_ALGO_SHA1));
    2683             :         }
    2684           0 :       tty_printf ("\n     ");
    2685           0 :       tty_printf (_("Compression: "));
    2686           0 :       for (i = any = 0; prefs[i].type; i++)
    2687             :         {
    2688           0 :           if (prefs[i].type == PREFTYPE_ZIP)
    2689             :             {
    2690           0 :               const char *s = compress_algo_to_string (prefs[i].value);
    2691             : 
    2692           0 :               if (any)
    2693           0 :                 tty_printf (", ");
    2694           0 :               any = 1;
    2695             :               /* We don't want to display strings for experimental algos */
    2696           0 :               if (s && prefs[i].value < 100)
    2697           0 :                 tty_printf ("%s", s);
    2698             :               else
    2699           0 :                 tty_printf ("[%d]", prefs[i].value);
    2700           0 :               if (prefs[i].value == COMPRESS_ALGO_NONE)
    2701           0 :                 uncomp_seen = 1;
    2702             :             }
    2703             :         }
    2704           0 :       if (!uncomp_seen)
    2705             :         {
    2706           0 :           if (any)
    2707           0 :             tty_printf (", ");
    2708             :           else
    2709             :             {
    2710           0 :               tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_ZIP));
    2711           0 :               tty_printf (", ");
    2712             :             }
    2713           0 :           tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
    2714             :         }
    2715           0 :       if (uid->flags.mdc || !uid->flags.ks_modify)
    2716             :         {
    2717           0 :           tty_printf ("\n     ");
    2718           0 :           tty_printf (_("Features: "));
    2719           0 :           any = 0;
    2720           0 :           if (uid->flags.mdc)
    2721             :             {
    2722           0 :               tty_printf ("MDC");
    2723           0 :               any = 1;
    2724             :             }
    2725           0 :           if (!uid->flags.ks_modify)
    2726             :             {
    2727           0 :               if (any)
    2728           0 :                 tty_printf (", ");
    2729           0 :               tty_printf (_("Keyserver no-modify"));
    2730             :             }
    2731             :         }
    2732           0 :       tty_printf ("\n");
    2733             : 
    2734           0 :       if (selfsig)
    2735             :         {
    2736             :           const byte *pref_ks;
    2737             :           size_t pref_ks_len;
    2738             : 
    2739           0 :           pref_ks = parse_sig_subpkt (selfsig->hashed,
    2740             :                                       SIGSUBPKT_PREF_KS, &pref_ks_len);
    2741           0 :           if (pref_ks && pref_ks_len)
    2742             :             {
    2743           0 :               tty_printf ("     ");
    2744           0 :               tty_printf (_("Preferred keyserver: "));
    2745           0 :               tty_print_utf8_string (pref_ks, pref_ks_len);
    2746           0 :               tty_printf ("\n");
    2747             :             }
    2748             : 
    2749           0 :           if (selfsig->flags.notation)
    2750             :             {
    2751           0 :               tty_printf ("     ");
    2752           0 :               tty_printf (_("Notations: "));
    2753           0 :               tty_print_notations (5 + strlen (_("Notations: ")), selfsig);
    2754             :             }
    2755             :         }
    2756             :     }
    2757             :   else
    2758             :     {
    2759           0 :       tty_printf ("    ");
    2760           0 :       for (i = 0; prefs[i].type; i++)
    2761             :         {
    2762           0 :           tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
    2763           0 :                       prefs[i].type == PREFTYPE_HASH ? 'H' :
    2764           0 :                       prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
    2765           0 :                       prefs[i].value);
    2766             :         }
    2767           0 :       if (uid->flags.mdc)
    2768           0 :         tty_printf (" [mdc]");
    2769           0 :       if (!uid->flags.ks_modify)
    2770           0 :         tty_printf (" [no-ks-modify]");
    2771           0 :       tty_printf ("\n");
    2772             :     }
    2773             : }
    2774             : 
    2775             : 
    2776             : /* This is the version of show_key_with_all_names used when
    2777             :    opt.with_colons is used.  It prints all available data in a easy to
    2778             :    parse format and does not translate utf8 */
    2779             : static void
    2780           0 : show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
    2781             : {
    2782             :   KBNODE node;
    2783           0 :   int i, j, ulti_hack = 0;
    2784           0 :   byte pk_version = 0;
    2785           0 :   PKT_public_key *primary = NULL;
    2786             :   int have_seckey;
    2787             : 
    2788           0 :   if (!fp)
    2789           0 :     fp = es_stdout;
    2790             : 
    2791             :   /* the keys */
    2792           0 :   for (node = keyblock; node; node = node->next)
    2793             :     {
    2794           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    2795           0 :           || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
    2796             :         {
    2797           0 :           PKT_public_key *pk = node->pkt->pkt.public_key;
    2798             :           u32 keyid[2];
    2799             : 
    2800           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    2801             :             {
    2802           0 :               pk_version = pk->version;
    2803           0 :               primary = pk;
    2804             :             }
    2805             : 
    2806           0 :           keyid_from_pk (pk, keyid);
    2807           0 :           have_seckey = !agent_probe_secret_key (ctrl, pk);
    2808             : 
    2809           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    2810           0 :             es_fputs (have_seckey? "sec:" : "pub:", fp);
    2811             :           else
    2812           0 :             es_fputs (have_seckey? "ssb:" : "sub:", fp);
    2813             : 
    2814           0 :           if (!pk->flags.valid)
    2815           0 :             es_putc ('i', fp);
    2816           0 :           else if (pk->flags.revoked)
    2817           0 :             es_putc ('r', fp);
    2818           0 :           else if (pk->has_expired)
    2819           0 :             es_putc ('e', fp);
    2820           0 :           else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks))
    2821             :             {
    2822           0 :               int trust = get_validity_info (pk, NULL);
    2823           0 :               if (trust == 'u')
    2824           0 :                 ulti_hack = 1;
    2825           0 :               es_putc (trust, fp);
    2826             :             }
    2827             : 
    2828           0 :           es_fprintf (fp, ":%u:%d:%08lX%08lX:%lu:%lu::",
    2829             :                       nbits_from_pk (pk),
    2830           0 :                       pk->pubkey_algo,
    2831           0 :                       (ulong) keyid[0], (ulong) keyid[1],
    2832           0 :                       (ulong) pk->timestamp, (ulong) pk->expiredate);
    2833           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY
    2834           0 :               && !(opt.fast_list_mode || opt.no_expensive_trust_checks))
    2835           0 :             es_putc (get_ownertrust_info (pk), fp);
    2836           0 :           es_putc (':', fp);
    2837           0 :           es_putc (':', fp);
    2838           0 :           es_putc (':', fp);
    2839             :           /* Print capabilities.  */
    2840           0 :           if ((pk->pubkey_usage & PUBKEY_USAGE_ENC))
    2841           0 :             es_putc ('e', fp);
    2842           0 :           if ((pk->pubkey_usage & PUBKEY_USAGE_SIG))
    2843           0 :             es_putc ('s', fp);
    2844           0 :           if ((pk->pubkey_usage & PUBKEY_USAGE_CERT))
    2845           0 :             es_putc ('c', fp);
    2846           0 :           if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
    2847           0 :             es_putc ('a', fp);
    2848           0 :           es_putc ('\n', fp);
    2849             : 
    2850           0 :           print_fingerprint (fp, pk, 0);
    2851           0 :           print_revokers (fp, pk);
    2852             :         }
    2853             :     }
    2854             : 
    2855             :   /* the user ids */
    2856           0 :   i = 0;
    2857           0 :   for (node = keyblock; node; node = node->next)
    2858             :     {
    2859           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    2860             :         {
    2861           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    2862             : 
    2863           0 :           ++i;
    2864             : 
    2865           0 :           if (uid->attrib_data)
    2866           0 :             es_fputs ("uat:", fp);
    2867             :           else
    2868           0 :             es_fputs ("uid:", fp);
    2869             : 
    2870           0 :           if (uid->is_revoked)
    2871           0 :             es_fputs ("r::::::::", fp);
    2872           0 :           else if (uid->is_expired)
    2873           0 :             es_fputs ("e::::::::", fp);
    2874           0 :           else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
    2875           0 :             es_fputs ("::::::::", fp);
    2876             :           else
    2877             :             {
    2878             :               int uid_validity;
    2879             : 
    2880           0 :               if (primary && !ulti_hack)
    2881           0 :                 uid_validity = get_validity_info (primary, uid);
    2882             :               else
    2883           0 :                 uid_validity = 'u';
    2884           0 :               es_fprintf (fp, "%c::::::::", uid_validity);
    2885             :             }
    2886             : 
    2887           0 :           if (uid->attrib_data)
    2888           0 :             es_fprintf (fp, "%u %lu", uid->numattribs, uid->attrib_len);
    2889             :           else
    2890           0 :             es_write_sanitized (fp, uid->name, uid->len, ":", NULL);
    2891             : 
    2892           0 :           es_putc (':', fp);
    2893             :           /* signature class */
    2894           0 :           es_putc (':', fp);
    2895             :           /* capabilities */
    2896           0 :           es_putc (':', fp);
    2897             :           /* preferences */
    2898           0 :           if (pk_version > 3 || uid->selfsigversion > 3)
    2899             :             {
    2900           0 :               const prefitem_t *prefs = uid->prefs;
    2901             : 
    2902           0 :               for (j = 0; prefs && prefs[j].type; j++)
    2903             :                 {
    2904           0 :                   if (j)
    2905           0 :                     es_putc (' ', fp);
    2906           0 :                   es_fprintf (fp,
    2907           0 :                               "%c%d", prefs[j].type == PREFTYPE_SYM ? 'S' :
    2908           0 :                               prefs[j].type == PREFTYPE_HASH ? 'H' :
    2909           0 :                               prefs[j].type == PREFTYPE_ZIP ? 'Z' : '?',
    2910           0 :                               prefs[j].value);
    2911             :                 }
    2912           0 :               if (uid->flags.mdc)
    2913           0 :                 es_fputs (",mdc", fp);
    2914           0 :               if (!uid->flags.ks_modify)
    2915           0 :                 es_fputs (",no-ks-modify", fp);
    2916             :             }
    2917           0 :           es_putc (':', fp);
    2918             :           /* flags */
    2919           0 :           es_fprintf (fp, "%d,", i);
    2920           0 :           if (uid->is_primary)
    2921           0 :             es_putc ('p', fp);
    2922           0 :           if (uid->is_revoked)
    2923           0 :             es_putc ('r', fp);
    2924           0 :           if (uid->is_expired)
    2925           0 :             es_putc ('e', fp);
    2926           0 :           if ((node->flag & NODFLG_SELUID))
    2927           0 :             es_putc ('s', fp);
    2928           0 :           if ((node->flag & NODFLG_MARK_A))
    2929           0 :             es_putc ('m', fp);
    2930           0 :           es_putc (':', fp);
    2931           0 :           if (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP)
    2932             :             {
    2933             : #ifdef USE_TOFU
    2934             :               enum tofu_policy policy;
    2935           0 :               if (! tofu_get_policy (primary, uid, &policy)
    2936           0 :                   && policy != TOFU_POLICY_NONE)
    2937           0 :                 es_fprintf (fp, "%s", tofu_policy_str (policy));
    2938             : #endif /*USE_TOFU*/
    2939             :             }
    2940           0 :           es_putc (':', fp);
    2941           0 :           es_putc ('\n', fp);
    2942             :         }
    2943             :     }
    2944           0 : }
    2945             : 
    2946             : 
    2947             : static void
    2948           0 : show_names (estream_t fp,
    2949             :             KBNODE keyblock, PKT_public_key * pk, unsigned int flag,
    2950             :             int with_prefs)
    2951             : {
    2952             :   KBNODE node;
    2953           0 :   int i = 0;
    2954             : 
    2955           0 :   for (node = keyblock; node; node = node->next)
    2956             :     {
    2957           0 :       if (node->pkt->pkttype == PKT_USER_ID && !is_deleted_kbnode (node))
    2958             :         {
    2959           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    2960           0 :           ++i;
    2961           0 :           if (!flag || (flag && (node->flag & flag)))
    2962             :             {
    2963           0 :               if (!(flag & NODFLG_MARK_A) && pk)
    2964           0 :                 tty_fprintf (fp, "%s ", uid_trust_string_fixed (pk, uid));
    2965             : 
    2966           0 :               if (flag & NODFLG_MARK_A)
    2967           0 :                 tty_fprintf (fp, "     ");
    2968           0 :               else if (node->flag & NODFLG_SELUID)
    2969           0 :                 tty_fprintf (fp, "(%d)* ", i);
    2970           0 :               else if (uid->is_primary)
    2971           0 :                 tty_fprintf (fp, "(%d). ", i);
    2972             :               else
    2973           0 :                 tty_fprintf (fp, "(%d)  ", i);
    2974           0 :               tty_print_utf8_string2 (fp, uid->name, uid->len, 0);
    2975           0 :               tty_fprintf (fp, "\n");
    2976           0 :               if (with_prefs && pk)
    2977             :                 {
    2978           0 :                   if (pk->version > 3 || uid->selfsigversion > 3)
    2979           0 :                     {
    2980           0 :                       PKT_signature *selfsig = NULL;
    2981             :                       KBNODE signode;
    2982             : 
    2983           0 :                       for (signode = node->next;
    2984           0 :                            signode && signode->pkt->pkttype == PKT_SIGNATURE;
    2985           0 :                            signode = signode->next)
    2986             :                         {
    2987           0 :                           if (signode->pkt->pkt.signature->
    2988             :                               flags.chosen_selfsig)
    2989             :                             {
    2990           0 :                               selfsig = signode->pkt->pkt.signature;
    2991           0 :                               break;
    2992             :                             }
    2993             :                         }
    2994             : 
    2995           0 :                       show_prefs (uid, selfsig, with_prefs == 2);
    2996             :                     }
    2997             :                   else
    2998           0 :                     tty_fprintf (fp, _("There are no preferences on a"
    2999             :                                        " PGP 2.x-style user ID.\n"));
    3000             :                 }
    3001             :             }
    3002             :         }
    3003             :     }
    3004           0 : }
    3005             : 
    3006             : 
    3007             : /*
    3008             :  * Display the key a the user ids, if only_marked is true, do only so
    3009             :  * for user ids with mark A flag set and do not display the index
    3010             :  * number.  If FP is not NULL print to the given stream and not to the
    3011             :  * tty (ignored in with-colons mode).
    3012             :  */
    3013             : static void
    3014           0 : show_key_with_all_names (ctrl_t ctrl, estream_t fp,
    3015             :                          KBNODE keyblock, int only_marked, int with_revoker,
    3016             :                          int with_fpr, int with_subkeys, int with_prefs,
    3017             :                          int nowarn)
    3018             : {
    3019             :   gpg_error_t err;
    3020             :   kbnode_t node;
    3021             :   int i;
    3022           0 :   int do_warn = 0;
    3023           0 :   int have_seckey = 0;
    3024           0 :   char *serialno = NULL;
    3025           0 :   PKT_public_key *primary = NULL;
    3026             :   char pkstrbuf[PUBKEY_STRING_SIZE];
    3027             : 
    3028           0 :   if (opt.with_colons)
    3029             :     {
    3030           0 :       show_key_with_all_names_colon (ctrl, fp, keyblock);
    3031           0 :       return;
    3032             :     }
    3033             : 
    3034             :   /* the keys */
    3035           0 :   for (node = keyblock; node; node = node->next)
    3036             :     {
    3037           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    3038           0 :           || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    3039           0 :               && !is_deleted_kbnode (node)))
    3040             :         {
    3041           0 :           PKT_public_key *pk = node->pkt->pkt.public_key;
    3042           0 :           const char *otrust = "err";
    3043           0 :           const char *trust = "err";
    3044             : 
    3045           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    3046             :             {
    3047             :               /* do it here, so that debug messages don't clutter the
    3048             :                * output */
    3049             :               static int did_warn = 0;
    3050             : 
    3051           0 :               trust = get_validity_string (pk, NULL);
    3052           0 :               otrust = get_ownertrust_string (pk);
    3053             : 
    3054             :               /* Show a warning once */
    3055           0 :               if (!did_warn
    3056           0 :                   && (get_validity (pk, NULL, NULL, 0)
    3057           0 :                       & TRUST_FLAG_PENDING_CHECK))
    3058             :                 {
    3059           0 :                   did_warn = 1;
    3060           0 :                   do_warn = 1;
    3061             :                 }
    3062             : 
    3063           0 :               primary = pk;
    3064             :             }
    3065             : 
    3066           0 :           if (pk->flags.revoked)
    3067             :             {
    3068           0 :               char *user = get_user_id_string_native (pk->revoked.keyid);
    3069           0 :               tty_fprintf (fp,
    3070           0 :                            _("The following key was revoked on"
    3071             :                             " %s by %s key %s\n"),
    3072             :                           revokestr_from_pk (pk),
    3073           0 :                           gcry_pk_algo_name (pk->revoked.algo), user);
    3074           0 :               xfree (user);
    3075             :             }
    3076             : 
    3077           0 :           if (with_revoker)
    3078             :             {
    3079           0 :               if (!pk->revkey && pk->numrevkeys)
    3080           0 :                 BUG ();
    3081             :               else
    3082           0 :                 for (i = 0; i < pk->numrevkeys; i++)
    3083             :                   {
    3084             :                     u32 r_keyid[2];
    3085             :                     char *user;
    3086             :                     const char *algo;
    3087             : 
    3088           0 :                     algo = gcry_pk_algo_name (pk->revkey[i].algid);
    3089           0 :                     keyid_from_fingerprint (pk->revkey[i].fpr,
    3090             :                                             MAX_FINGERPRINT_LEN, r_keyid);
    3091             : 
    3092           0 :                     user = get_user_id_string_native (r_keyid);
    3093           0 :                     tty_fprintf (fp,
    3094           0 :                                  _("This key may be revoked by %s key %s"),
    3095             :                                  algo ? algo : "?", user);
    3096             : 
    3097           0 :                     if (pk->revkey[i].class & 0x40)
    3098             :                       {
    3099           0 :                         tty_fprintf (fp, " ");
    3100           0 :                         tty_fprintf (fp, _("(sensitive)"));
    3101             :                       }
    3102             : 
    3103           0 :                     tty_fprintf (fp, "\n");
    3104           0 :                     xfree (user);
    3105             :                   }
    3106             :             }
    3107             : 
    3108           0 :           keyid_from_pk (pk, NULL);
    3109             : 
    3110           0 :           xfree (serialno);
    3111           0 :           serialno = NULL;
    3112             :           {
    3113             :             char *hexgrip;
    3114             : 
    3115           0 :             err = hexkeygrip_from_pk (pk, &hexgrip);
    3116           0 :             if (err)
    3117             :               {
    3118           0 :                 log_error ("error computing a keygrip: %s\n",
    3119             :                            gpg_strerror (err));
    3120           0 :                 have_seckey = 0;
    3121             :               }
    3122             :             else
    3123           0 :               have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno);
    3124           0 :             xfree (hexgrip);
    3125             :           }
    3126             : 
    3127           0 :           tty_fprintf
    3128             :             (fp, "%s%c %s/%s",
    3129           0 :              node->pkt->pkttype == PKT_PUBLIC_KEY && have_seckey? "sec" :
    3130           0 :              node->pkt->pkttype == PKT_PUBLIC_KEY ?               "pub" :
    3131           0 :              have_seckey ?                                        "ssb" :
    3132             :                                                                   "sub",
    3133           0 :              (node->flag & NODFLG_SELKEY) ? '*' : ' ',
    3134             :              pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    3135           0 :              keystr (pk->keyid));
    3136             : 
    3137           0 :           if (opt.legacy_list_mode)
    3138           0 :             tty_fprintf (fp, "  ");
    3139             :           else
    3140           0 :             tty_fprintf (fp, "\n     ");
    3141             : 
    3142           0 :           tty_fprintf (fp, _("created: %s"), datestr_from_pk (pk));
    3143           0 :           tty_fprintf (fp, "  ");
    3144           0 :           if (pk->flags.revoked)
    3145           0 :             tty_fprintf (fp, _("revoked: %s"), revokestr_from_pk (pk));
    3146           0 :           else if (pk->has_expired)
    3147           0 :             tty_fprintf (fp, _("expired: %s"), expirestr_from_pk (pk));
    3148             :           else
    3149           0 :             tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
    3150           0 :           tty_fprintf (fp, "  ");
    3151           0 :           tty_fprintf (fp, _("usage: %s"), usagestr_from_pk (pk, 1));
    3152           0 :           tty_fprintf (fp, "\n");
    3153             : 
    3154           0 :           if (serialno)
    3155             :             {
    3156             :               /* The agent told us that a secret key is available and
    3157             :                  that it has been stored on a card.  */
    3158           0 :               tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
    3159             :                            _("card-no: "));
    3160           0 :               if (strlen (serialno) == 32
    3161           0 :                   && !strncmp (serialno, "D27600012401", 12))
    3162             :                 {
    3163             :                   /* This is an OpenPGP card.  Print the relevant part.  */
    3164             :                   /* Example: D2760001240101010001000003470000 */
    3165             :                   /*                          xxxxyyyyyyyy     */
    3166           0 :                   tty_fprintf (fp, "%.*s %.*s\n",
    3167             :                                4, serialno+16, 8, serialno+20);
    3168             :                 }
    3169             :               else
    3170           0 :                 tty_fprintf (fp, "%s\n", serialno);
    3171             : 
    3172             :             }
    3173           0 :           else if (pk->seckey_info
    3174           0 :               && pk->seckey_info->is_protected
    3175           0 :               && pk->seckey_info->s2k.mode == 1002)
    3176             :             {
    3177             :               /* FIXME: Check wether this code path is still used.  */
    3178           0 :               tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
    3179             :                            _("card-no: "));
    3180           0 :               if (pk->seckey_info->ivlen == 16
    3181           0 :                   && !memcmp (pk->seckey_info->iv,
    3182             :                               "\xD2\x76\x00\x01\x24\x01", 6))
    3183             :                 {
    3184             :                   /* This is an OpenPGP card. */
    3185           0 :                   for (i = 8; i < 14; i++)
    3186             :                     {
    3187           0 :                       if (i == 10)
    3188           0 :                         tty_fprintf (fp, " ");
    3189           0 :                       tty_fprintf (fp, "%02X", pk->seckey_info->iv[i]);
    3190             :                     }
    3191             :                 }
    3192             :               else
    3193             :                 {
    3194             :                   /* Unknown card: Print all. */
    3195           0 :                   for (i = 0; i < pk->seckey_info->ivlen; i++)
    3196           0 :                     tty_fprintf (fp, "%02X", pk->seckey_info->iv[i]);
    3197             :                 }
    3198           0 :               tty_fprintf (fp, "\n");
    3199             :             }
    3200             : 
    3201           0 :           if (node->pkt->pkttype == PKT_PUBLIC_KEY
    3202           0 :               || node->pkt->pkttype == PKT_SECRET_KEY)
    3203             :             {
    3204           0 :               if (opt.trust_model != TM_ALWAYS)
    3205             :                 {
    3206           0 :                   tty_fprintf (fp, "%*s",
    3207           0 :                                opt.legacy_list_mode?
    3208           0 :                                ((int) keystrlen () + 13):5, "");
    3209             :                   /* Ownertrust is only meaningful for the PGP or
    3210             :                      classic trust models */
    3211           0 :                   if (opt.trust_model == TM_PGP
    3212           0 :                       || opt.trust_model == TM_CLASSIC)
    3213             :                     {
    3214           0 :                       int width = 14 - strlen (otrust);
    3215           0 :                       if (width <= 0)
    3216           0 :                         width = 1;
    3217           0 :                       tty_fprintf (fp, _("trust: %s"), otrust);
    3218           0 :                       tty_fprintf (fp, "%*s", width, "");
    3219             :                     }
    3220             : 
    3221           0 :                   tty_fprintf (fp, _("validity: %s"), trust);
    3222           0 :                   tty_fprintf (fp, "\n");
    3223             :                 }
    3224           0 :               if (node->pkt->pkttype == PKT_PUBLIC_KEY
    3225           0 :                   && (get_ownertrust (pk) & TRUST_FLAG_DISABLED))
    3226             :                 {
    3227           0 :                   tty_fprintf (fp, "*** ");
    3228           0 :                   tty_fprintf (fp, _("This key has been disabled"));
    3229           0 :                   tty_fprintf (fp, "\n");
    3230             :                 }
    3231             :             }
    3232             : 
    3233           0 :           if ((node->pkt->pkttype == PKT_PUBLIC_KEY
    3234           0 :                || node->pkt->pkttype == PKT_SECRET_KEY) && with_fpr)
    3235             :             {
    3236           0 :               print_fingerprint (fp, pk, 2);
    3237           0 :               tty_fprintf (fp, "\n");
    3238             :             }
    3239             :         }
    3240             :     }
    3241             : 
    3242           0 :   show_names (fp,
    3243             :               keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
    3244             : 
    3245           0 :   if (do_warn && !nowarn)
    3246           0 :     tty_fprintf (fp, _("Please note that the shown key validity"
    3247             :                        " is not necessarily correct\n"
    3248             :                        "unless you restart the program.\n"));
    3249             : 
    3250           0 :   xfree (serialno);
    3251             : }
    3252             : 
    3253             : 
    3254             : /* Display basic key information.  This function is suitable to show
    3255             :    information on the key without any dependencies on the trustdb or
    3256             :    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
    3257             :    a secret key.  This function may be called with KEYBLOCK containing
    3258             :    secret keys and thus the printing of "pub" vs. "sec" does only
    3259             :    depend on the packet type and not by checking with gpg-agent.  */
    3260             : void
    3261           0 : show_basic_key_info (KBNODE keyblock)
    3262             : {
    3263             :   KBNODE node;
    3264             :   int i;
    3265             :   char pkstrbuf[PUBKEY_STRING_SIZE];
    3266             : 
    3267             :   /* The primary key */
    3268           0 :   for (node = keyblock; node; node = node->next)
    3269             :     {
    3270           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    3271           0 :           || node->pkt->pkttype == PKT_SECRET_KEY)
    3272             :         {
    3273           0 :           PKT_public_key *pk = node->pkt->pkt.public_key;
    3274             : 
    3275             :           /* Note, we use the same format string as in other show
    3276             :              functions to make the translation job easier. */
    3277           0 :           tty_printf ("%s  %s/%s  ",
    3278           0 :                       node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" :
    3279           0 :                       node->pkt->pkttype == PKT_PUBLIC_SUBKEY ? "sub" :
    3280           0 :                       node->pkt->pkttype == PKT_SECRET_KEY ? "sec" :"ssb",
    3281             :                       pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    3282             :                       keystr_from_pk (pk));
    3283           0 :           tty_printf (_("created: %s"), datestr_from_pk (pk));
    3284           0 :           tty_printf ("  ");
    3285           0 :           tty_printf (_("expires: %s"), expirestr_from_pk (pk));
    3286           0 :           tty_printf ("\n");
    3287           0 :           print_fingerprint (NULL, pk, 3);
    3288           0 :           tty_printf ("\n");
    3289             :         }
    3290             :     }
    3291             : 
    3292             :   /* The user IDs. */
    3293           0 :   for (i = 0, node = keyblock; node; node = node->next)
    3294             :     {
    3295           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    3296             :         {
    3297           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    3298           0 :           ++i;
    3299             : 
    3300           0 :           tty_printf ("     ");
    3301           0 :           if (uid->is_revoked)
    3302           0 :             tty_printf ("[%s] ", _("revoked"));
    3303           0 :           else if (uid->is_expired)
    3304           0 :             tty_printf ("[%s] ", _("expired"));
    3305           0 :           tty_print_utf8_string (uid->name, uid->len);
    3306           0 :           tty_printf ("\n");
    3307             :         }
    3308             :     }
    3309           0 : }
    3310             : 
    3311             : 
    3312             : static void
    3313           0 : show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys)
    3314             : {
    3315             :   kbnode_t node;
    3316           0 :   PKT_public_key *pk = NULL;
    3317             :   char pkstrbuf[PUBKEY_STRING_SIZE];
    3318             : 
    3319           0 :   for (node = keyblock; node; node = node->next)
    3320             :     {
    3321           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    3322             :         {
    3323           0 :           pk = node->pkt->pkt.public_key;
    3324           0 :           tty_printf ("pub   %s/%s %s ",
    3325             :                       pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    3326             :                       keystr_from_pk(pk),
    3327             :                       datestr_from_pk (pk));
    3328             :         }
    3329           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    3330             :         {
    3331           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    3332           0 :           tty_print_utf8_string (uid->name, uid->len);
    3333           0 :           break;
    3334             :         }
    3335             :     }
    3336           0 :   tty_printf ("\n");
    3337           0 :   if (pk)
    3338           0 :     print_fingerprint (NULL, pk, 2);
    3339           0 :   if (with_subkeys)
    3340             :     {
    3341           0 :       for (node = keyblock; node; node = node->next)
    3342             :         {
    3343           0 :           if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3344             :             {
    3345           0 :               pk = node->pkt->pkt.public_key;
    3346           0 :               tty_printf ("sub   %s/%s %s [%s]\n",
    3347             :                           pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    3348             :                           keystr_from_pk(pk),
    3349             :                           datestr_from_pk (pk),
    3350             :                           usagestr_from_pk (pk, 0));
    3351             : 
    3352           0 :               print_fingerprint (NULL, pk, 4);
    3353             :             }
    3354             :         }
    3355             :     }
    3356           0 : }
    3357             : 
    3358             : 
    3359             : /* Show a listing of the primary and its subkeys along with their
    3360             :    keygrips.  */
    3361             : static void
    3362           0 : show_key_and_grip (kbnode_t keyblock)
    3363             : {
    3364             :   kbnode_t node;
    3365           0 :   PKT_public_key *pk = NULL;
    3366             :   char pkstrbuf[PUBKEY_STRING_SIZE];
    3367             :   char *hexgrip;
    3368             : 
    3369           0 :   for (node = keyblock; node; node = node->next)
    3370             :     {
    3371           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY
    3372           0 :           || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3373             :         {
    3374           0 :           pk = node->pkt->pkt.public_key;
    3375           0 :           tty_printf ("%s   %s/%s %s [%s]\n",
    3376           0 :                       node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
    3377             :                       pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
    3378             :                       keystr_from_pk(pk),
    3379             :                       datestr_from_pk (pk),
    3380             :                       usagestr_from_pk (pk, 0));
    3381             : 
    3382           0 :           if (!hexkeygrip_from_pk (pk, &hexgrip))
    3383             :             {
    3384           0 :               tty_printf ("      Keygrip: %s\n", hexgrip);
    3385           0 :               xfree (hexgrip);
    3386             :             }
    3387             :         }
    3388             :     }
    3389           0 : }
    3390             : 
    3391             : 
    3392             : /* Show a warning if no uids on the key have the primary uid flag
    3393             :    set. */
    3394             : static void
    3395           0 : no_primary_warning (KBNODE keyblock)
    3396             : {
    3397             :   KBNODE node;
    3398           0 :   int have_primary = 0, uid_count = 0;
    3399             : 
    3400             :   /* TODO: if we ever start behaving differently with a primary or
    3401             :      non-primary attribute ID, we will need to check for attributes
    3402             :      here as well. */
    3403             : 
    3404           0 :   for (node = keyblock; node; node = node->next)
    3405             :     {
    3406           0 :       if (node->pkt->pkttype == PKT_USER_ID
    3407           0 :           && node->pkt->pkt.user_id->attrib_data == NULL)
    3408             :         {
    3409           0 :           uid_count++;
    3410             : 
    3411           0 :           if (node->pkt->pkt.user_id->is_primary == 2)
    3412             :             {
    3413           0 :               have_primary = 1;
    3414           0 :               break;
    3415             :             }
    3416             :         }
    3417             :     }
    3418             : 
    3419           0 :   if (uid_count > 1 && !have_primary)
    3420           0 :     log_info (_
    3421             :               ("WARNING: no user ID has been marked as primary.  This command"
    3422             :                " may\n              cause a different user ID to become"
    3423             :                " the assumed primary.\n"));
    3424           0 : }
    3425             : 
    3426             : 
    3427             : /* Print a warning if the latest encryption subkey expires soon.  This
    3428             :    function is called after the expire data of the primary key has
    3429             :    been changed.  */
    3430             : static void
    3431           0 : subkey_expire_warning (kbnode_t keyblock)
    3432             : {
    3433           0 :   u32 curtime = make_timestamp ();
    3434             :   kbnode_t node;
    3435             :   PKT_public_key *pk;
    3436             :   /* u32 mainexpire = 0; */
    3437           0 :   u32 subexpire = 0;
    3438           0 :   u32 latest_date = 0;
    3439             : 
    3440           0 :   for (node = keyblock; node; node = node->next)
    3441             :     {
    3442             :       /* if (node->pkt->pkttype == PKT_PUBLIC_KEY) */
    3443             :       /*   { */
    3444             :       /*     pk = node->pkt->pkt.public_key; */
    3445             :       /*     mainexpire = pk->expiredate; */
    3446             :       /*   } */
    3447             : 
    3448           0 :       if (node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
    3449           0 :         continue;
    3450           0 :       pk = node->pkt->pkt.public_key;
    3451             : 
    3452           0 :       if (!pk->flags.valid)
    3453           0 :         continue;
    3454           0 :       if (pk->flags.revoked)
    3455           0 :         continue;
    3456           0 :       if (pk->timestamp > curtime)
    3457           0 :         continue; /* Ignore future keys.  */
    3458           0 :       if (!(pk->pubkey_usage & PUBKEY_USAGE_ENC))
    3459           0 :         continue; /* Not an encryption key.  */
    3460             : 
    3461           0 :       if (pk->timestamp > latest_date || (!pk->timestamp && !latest_date))
    3462             :         {
    3463           0 :           latest_date = pk->timestamp;
    3464           0 :           subexpire = pk->expiredate;
    3465             :         }
    3466             :     }
    3467             : 
    3468           0 :   if (!subexpire)
    3469           0 :     return;  /* No valid subkey with an expiration time.  */
    3470             : 
    3471           0 :   if (curtime + (10*86400) > subexpire)
    3472             :     {
    3473           0 :       log_info (_("WARNING: Your encryption subkey expires soon.\n"));
    3474           0 :       log_info (_("You may want to change its expiration date too.\n"));
    3475             :     }
    3476             : }
    3477             : 
    3478             : 
    3479             : /*
    3480             :  * Ask for a new user id, add the self-signature, and update the
    3481             :  * keyblock.  If UIDSTRING is not NULL the user ID is generated
    3482             :  * unattended using that string.  UIDSTRING is expected to be utf-8
    3483             :  * encoded and white space trimmed.  Returns true if there is a new
    3484             :  * user id.
    3485             :  */
    3486             : static int
    3487           0 : menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
    3488             :              const char *uidstring)
    3489             : {
    3490             :   PKT_user_id *uid;
    3491           0 :   PKT_public_key *pk = NULL;
    3492           0 :   PKT_signature *sig = NULL;
    3493             :   PACKET *pkt;
    3494             :   KBNODE node;
    3495           0 :   KBNODE pub_where = NULL;
    3496             :   gpg_error_t err;
    3497             : 
    3498           0 :   if (photo && uidstring)
    3499           0 :     return 0;  /* Not allowed.  */
    3500             : 
    3501           0 :   for (node = pub_keyblock; node; pub_where = node, node = node->next)
    3502             :     {
    3503           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    3504           0 :         pk = node->pkt->pkt.public_key;
    3505           0 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3506           0 :         break;
    3507             :     }
    3508           0 :   if (!node) /* No subkey.  */
    3509           0 :     pub_where = NULL;
    3510           0 :   assert (pk);
    3511             : 
    3512           0 :   if (photo)
    3513             :     {
    3514           0 :       int hasattrib = 0;
    3515             : 
    3516           0 :       for (node = pub_keyblock; node; node = node->next)
    3517           0 :         if (node->pkt->pkttype == PKT_USER_ID &&
    3518           0 :             node->pkt->pkt.user_id->attrib_data != NULL)
    3519             :           {
    3520           0 :             hasattrib = 1;
    3521           0 :             break;
    3522             :           }
    3523             : 
    3524             :       /* It is legal but bad for compatibility to add a photo ID to a
    3525             :          v3 key as it means that PGP2 will not be able to use that key
    3526             :          anymore.  Also, PGP may not expect a photo on a v3 key.
    3527             :          Don't bother to ask this if the key already has a photo - any
    3528             :          damage has already been done at that point. -dms */
    3529           0 :       if (pk->version == 3 && !hasattrib)
    3530             :         {
    3531           0 :           if (opt.expert)
    3532             :             {
    3533           0 :               tty_printf (_("WARNING: This is a PGP2-style key.  "
    3534             :                             "Adding a photo ID may cause some versions\n"
    3535             :                             "         of PGP to reject this key.\n"));
    3536             : 
    3537           0 :               if (!cpr_get_answer_is_yes ("keyedit.v3_photo.okay",
    3538           0 :                                           _("Are you sure you still want "
    3539             :                                             "to add it? (y/N) ")))
    3540           0 :                 return 0;
    3541             :             }
    3542             :           else
    3543             :             {
    3544           0 :               tty_printf (_("You may not add a photo ID to "
    3545             :                             "a PGP2-style key.\n"));
    3546           0 :               return 0;
    3547             :             }
    3548             :         }
    3549             : 
    3550           0 :       uid = generate_photo_id (pk, photo_name);
    3551             :     }
    3552             :   else
    3553           0 :     uid = generate_user_id (pub_keyblock, uidstring);
    3554           0 :   if (!uid)
    3555             :     {
    3556           0 :       if (uidstring)
    3557           0 :         log_error ("%s", _("Such a user ID already exists on this key!\n"));
    3558           0 :       return 0;
    3559             :     }
    3560             : 
    3561           0 :   err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
    3562             :                             keygen_add_std_prefs, pk, NULL);
    3563           0 :   if (err)
    3564             :     {
    3565           0 :       write_status_error ("keysig", err);
    3566           0 :       log_error ("signing failed: %s\n", gpg_strerror (err));
    3567           0 :       free_user_id (uid);
    3568           0 :       return 0;
    3569             :     }
    3570             : 
    3571             :   /* Insert/append to public keyblock */
    3572           0 :   pkt = xmalloc_clear (sizeof *pkt);
    3573           0 :   pkt->pkttype = PKT_USER_ID;
    3574           0 :   pkt->pkt.user_id = uid;
    3575           0 :   node = new_kbnode (pkt);
    3576           0 :   if (pub_where)
    3577           0 :     insert_kbnode (pub_where, node, 0);
    3578             :   else
    3579           0 :     add_kbnode (pub_keyblock, node);
    3580           0 :   pkt = xmalloc_clear (sizeof *pkt);
    3581           0 :   pkt->pkttype = PKT_SIGNATURE;
    3582           0 :   pkt->pkt.signature = copy_signature (NULL, sig);
    3583           0 :   if (pub_where)
    3584           0 :     insert_kbnode (node, new_kbnode (pkt), 0);
    3585             :   else
    3586           0 :     add_kbnode (pub_keyblock, new_kbnode (pkt));
    3587           0 :   return 1;
    3588             : }
    3589             : 
    3590             : 
    3591             : /*
    3592             :  * Remove all selected userids from the keyring
    3593             :  */
    3594             : static void
    3595           0 : menu_deluid (KBNODE pub_keyblock)
    3596             : {
    3597             :   KBNODE node;
    3598           0 :   int selected = 0;
    3599             : 
    3600           0 :   for (node = pub_keyblock; node; node = node->next)
    3601             :     {
    3602           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    3603             :         {
    3604           0 :           selected = node->flag & NODFLG_SELUID;
    3605           0 :           if (selected)
    3606             :             {
    3607             :               /* Only cause a trust update if we delete a
    3608             :                  non-revoked user id */
    3609           0 :               if (!node->pkt->pkt.user_id->is_revoked)
    3610           0 :                 update_trust = 1;
    3611           0 :               delete_kbnode (node);
    3612             :             }
    3613             :         }
    3614           0 :       else if (selected && node->pkt->pkttype == PKT_SIGNATURE)
    3615           0 :         delete_kbnode (node);
    3616           0 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3617           0 :         selected = 0;
    3618             :     }
    3619           0 :   commit_kbnode (&pub_keyblock);
    3620           0 : }
    3621             : 
    3622             : 
    3623             : static int
    3624           0 : menu_delsig (KBNODE pub_keyblock)
    3625             : {
    3626             :   KBNODE node;
    3627           0 :   PKT_user_id *uid = NULL;
    3628           0 :   int changed = 0;
    3629             : 
    3630           0 :   for (node = pub_keyblock; node; node = node->next)
    3631             :     {
    3632           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    3633             :         {
    3634           0 :           uid = (node->flag & NODFLG_SELUID) ? node->pkt->pkt.user_id : NULL;
    3635             :         }
    3636           0 :       else if (uid && node->pkt->pkttype == PKT_SIGNATURE)
    3637           0 :         {
    3638             :           int okay, valid, selfsig, inv_sig, no_key, other_err;
    3639             : 
    3640           0 :           tty_printf ("uid  ");
    3641           0 :           tty_print_utf8_string (uid->name, uid->len);
    3642           0 :           tty_printf ("\n");
    3643             : 
    3644           0 :           okay = inv_sig = no_key = other_err = 0;
    3645           0 :           if (opt.with_colons)
    3646           0 :             valid = print_and_check_one_sig_colon (pub_keyblock, node,
    3647             :                                                    &inv_sig, &no_key,
    3648             :                                                    &other_err, &selfsig, 1);
    3649             :           else
    3650           0 :             valid = print_and_check_one_sig (pub_keyblock, node,
    3651             :                                              &inv_sig, &no_key, &other_err,
    3652             :                                              &selfsig, 1, 0);
    3653             : 
    3654           0 :           if (valid)
    3655             :             {
    3656           0 :               okay = cpr_get_answer_yes_no_quit
    3657             :                 ("keyedit.delsig.valid",
    3658           0 :                  _("Delete this good signature? (y/N/q)"));
    3659             : 
    3660             :               /* Only update trust if we delete a good signature.
    3661             :                  The other two cases do not affect trust. */
    3662           0 :               if (okay)
    3663           0 :                 update_trust = 1;
    3664             :             }
    3665           0 :           else if (inv_sig || other_err)
    3666           0 :             okay = cpr_get_answer_yes_no_quit
    3667             :               ("keyedit.delsig.invalid",
    3668           0 :                _("Delete this invalid signature? (y/N/q)"));
    3669           0 :           else if (no_key)
    3670           0 :             okay = cpr_get_answer_yes_no_quit
    3671             :               ("keyedit.delsig.unknown",
    3672           0 :                _("Delete this unknown signature? (y/N/q)"));
    3673             : 
    3674           0 :           if (okay == -1)
    3675           0 :             break;
    3676           0 :           if (okay && selfsig
    3677           0 :               && !cpr_get_answer_is_yes
    3678             :               ("keyedit.delsig.selfsig",
    3679           0 :                _("Really delete this self-signature? (y/N)")))
    3680           0 :             okay = 0;
    3681           0 :           if (okay)
    3682             :             {
    3683           0 :               delete_kbnode (node);
    3684           0 :               changed++;
    3685             :             }
    3686             : 
    3687             :         }
    3688           0 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3689           0 :         uid = NULL;
    3690             :     }
    3691             : 
    3692           0 :   if (changed)
    3693             :     {
    3694           0 :       commit_kbnode (&pub_keyblock);
    3695           0 :       tty_printf (changed == 1 ? _("Deleted %d signature.\n")
    3696             :                   : _("Deleted %d signatures.\n"), changed);
    3697             :     }
    3698             :   else
    3699           0 :     tty_printf (_("Nothing deleted.\n"));
    3700             : 
    3701           0 :   return changed;
    3702             : }
    3703             : 
    3704             : 
    3705             : static int
    3706           0 : menu_clean (KBNODE keyblock, int self_only)
    3707             : {
    3708             :   KBNODE uidnode;
    3709           0 :   int modified = 0, select_all = !count_selected_uids (keyblock);
    3710             : 
    3711           0 :   for (uidnode = keyblock->next;
    3712           0 :        uidnode && uidnode->pkt->pkttype != PKT_PUBLIC_SUBKEY;
    3713           0 :        uidnode = uidnode->next)
    3714             :     {
    3715           0 :       if (uidnode->pkt->pkttype == PKT_USER_ID
    3716           0 :           && (uidnode->flag & NODFLG_SELUID || select_all))
    3717             :         {
    3718           0 :           int uids = 0, sigs = 0;
    3719           0 :           char *user = utf8_to_native (uidnode->pkt->pkt.user_id->name,
    3720           0 :                                        uidnode->pkt->pkt.user_id->len,
    3721             :                                        0);
    3722             : 
    3723           0 :           clean_one_uid (keyblock, uidnode, opt.verbose, self_only, &uids,
    3724             :                          &sigs);
    3725           0 :           if (uids)
    3726             :             {
    3727             :               const char *reason;
    3728             : 
    3729           0 :               if (uidnode->pkt->pkt.user_id->is_revoked)
    3730           0 :                 reason = _("revoked");
    3731           0 :               else if (uidnode->pkt->pkt.user_id->is_expired)
    3732           0 :                 reason = _("expired");
    3733             :               else
    3734           0 :                 reason = _("invalid");
    3735             : 
    3736           0 :               tty_printf (_("User ID \"%s\" compacted: %s\n"), user, reason);
    3737             : 
    3738           0 :               modified = 1;
    3739             :             }
    3740           0 :           else if (sigs)
    3741             :             {
    3742           0 :               tty_printf (sigs == 1 ?
    3743             :                           _("User ID \"%s\": %d signature removed\n") :
    3744             :                           _("User ID \"%s\": %d signatures removed\n"),
    3745             :                           user, sigs);
    3746             : 
    3747           0 :               modified = 1;
    3748             :             }
    3749             :           else
    3750             :             {
    3751           0 :               tty_printf (self_only == 1 ?
    3752             :                           _("User ID \"%s\": already minimized\n") :
    3753             :                           _("User ID \"%s\": already clean\n"), user);
    3754             :             }
    3755             : 
    3756           0 :           xfree (user);
    3757             :         }
    3758             :     }
    3759             : 
    3760           0 :   return modified;
    3761             : }
    3762             : 
    3763             : 
    3764             : /*
    3765             :  * Remove some of the secondary keys
    3766             :  */
    3767             : static void
    3768           0 : menu_delkey (KBNODE pub_keyblock)
    3769             : {
    3770             :   KBNODE node;
    3771           0 :   int selected = 0;
    3772             : 
    3773           0 :   for (node = pub_keyblock; node; node = node->next)
    3774             :     {
    3775           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    3776             :         {
    3777           0 :           selected = node->flag & NODFLG_SELKEY;
    3778           0 :           if (selected)
    3779           0 :             delete_kbnode (node);
    3780             :         }
    3781           0 :       else if (selected && node->pkt->pkttype == PKT_SIGNATURE)
    3782           0 :         delete_kbnode (node);
    3783             :       else
    3784           0 :         selected = 0;
    3785             :     }
    3786           0 :   commit_kbnode (&pub_keyblock);
    3787             : 
    3788             :   /* No need to set update_trust here since signing keys are no
    3789             :      longer used to certify other keys, so there is no change in
    3790             :      trust when revoking/removing them.   */
    3791           0 : }
    3792             : 
    3793             : 
    3794             : /*
    3795             :  * Ask for a new revoker, create the self-signature and put it into
    3796             :  * the keyblock.  Returns true if there is a new revoker.
    3797             :  */
    3798             : static int
    3799           0 : menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
    3800             : {
    3801           0 :   PKT_public_key *pk = NULL;
    3802           0 :   PKT_public_key *revoker_pk = NULL;
    3803           0 :   PKT_signature *sig = NULL;
    3804             :   PACKET *pkt;
    3805             :   struct revocation_key revkey;
    3806             :   size_t fprlen;
    3807             :   int rc;
    3808             : 
    3809           0 :   assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
    3810             : 
    3811           0 :   pk = pub_keyblock->pkt->pkt.public_key;
    3812             : 
    3813           0 :   if (pk->numrevkeys == 0 && pk->version == 3)
    3814             :     {
    3815             :       /* It is legal but bad for compatibility to add a revoker to a
    3816             :          v3 key as it means that PGP2 will not be able to use that key
    3817             :          anymore.  Also, PGP may not expect a revoker on a v3 key.
    3818             :          Don't bother to ask this if the key already has a revoker -
    3819             :          any damage has already been done at that point. -dms */
    3820           0 :       if (opt.expert)
    3821             :         {
    3822           0 :           tty_printf (_("WARNING: This is a PGP 2.x-style key.  "
    3823             :                         "Adding a designated revoker may cause\n"
    3824             :                         "         some versions of PGP to reject this key.\n"));
    3825             : 
    3826           0 :           if (!cpr_get_answer_is_yes ("keyedit.v3_revoker.okay",
    3827           0 :                                       _("Are you sure you still want "
    3828             :                                         "to add it? (y/N) ")))
    3829           0 :             return 0;
    3830             :         }
    3831             :       else
    3832             :         {
    3833           0 :           tty_printf (_("You may not add a designated revoker to "
    3834             :                         "a PGP 2.x-style key.\n"));
    3835           0 :           return 0;
    3836             :         }
    3837             :     }
    3838             : 
    3839             :   for (;;)
    3840             :     {
    3841             :       char *answer;
    3842             : 
    3843           0 :       free_public_key (revoker_pk);
    3844           0 :       revoker_pk = xmalloc_clear (sizeof (*revoker_pk));
    3845             : 
    3846           0 :       tty_printf ("\n");
    3847             : 
    3848           0 :       answer = cpr_get_utf8
    3849             :         ("keyedit.add_revoker",
    3850           0 :          _("Enter the user ID of the designated revoker: "));
    3851           0 :       if (answer[0] == '\0' || answer[0] == CONTROL_D)
    3852             :         {
    3853           0 :           xfree (answer);
    3854           0 :           goto fail;
    3855             :         }
    3856             : 
    3857             :       /* Note that I'm requesting CERT here, which usually implies
    3858             :          primary keys only, but some casual testing shows that PGP and
    3859             :          GnuPG both can handle a designated revocation from a subkey. */
    3860           0 :       revoker_pk->req_usage = PUBKEY_USAGE_CERT;
    3861           0 :       rc = get_pubkey_byname (ctrl, NULL, revoker_pk, answer, NULL, NULL, 1, 1);
    3862           0 :       if (rc)
    3863             :         {
    3864           0 :           log_error (_("key \"%s\" not found: %s\n"), answer,
    3865             :                      gpg_strerror (rc));
    3866           0 :           xfree (answer);
    3867           0 :           continue;
    3868             :         }
    3869             : 
    3870           0 :       xfree (answer);
    3871             : 
    3872           0 :       fingerprint_from_pk (revoker_pk, revkey.fpr, &fprlen);
    3873           0 :       if (fprlen != 20)
    3874             :         {
    3875           0 :           log_error (_("cannot appoint a PGP 2.x style key as a "
    3876             :                        "designated revoker\n"));
    3877           0 :           continue;
    3878             :         }
    3879             : 
    3880           0 :       revkey.class = 0x80;
    3881           0 :       if (sensitive)
    3882           0 :         revkey.class |= 0x40;
    3883           0 :       revkey.algid = revoker_pk->pubkey_algo;
    3884             : 
    3885           0 :       if (cmp_public_keys (revoker_pk, pk) == 0)
    3886             :         {
    3887             :           /* This actually causes no harm (after all, a key that
    3888             :              designates itself as a revoker is the same as a
    3889             :              regular key), but it's easy enough to check. */
    3890           0 :           log_error (_("you cannot appoint a key as its own "
    3891             :                        "designated revoker\n"));
    3892             : 
    3893           0 :           continue;
    3894             :         }
    3895             : 
    3896           0 :       keyid_from_pk (pk, NULL);
    3897             : 
    3898             :       /* Does this revkey already exist? */
    3899           0 :       if (!pk->revkey && pk->numrevkeys)
    3900           0 :         BUG ();
    3901             :       else
    3902             :         {
    3903             :           int i;
    3904             : 
    3905           0 :           for (i = 0; i < pk->numrevkeys; i++)
    3906             :             {
    3907           0 :               if (memcmp (&pk->revkey[i], &revkey,
    3908             :                           sizeof (struct revocation_key)) == 0)
    3909             :                 {
    3910             :                   char buf[50];
    3911             : 
    3912           0 :                   log_error (_("this key has already been designated "
    3913             :                                "as a revoker\n"));
    3914             : 
    3915           0 :                   sprintf (buf, "%08lX%08lX",
    3916           0 :                            (ulong) pk->keyid[0], (ulong) pk->keyid[1]);
    3917           0 :                   write_status_text (STATUS_ALREADY_SIGNED, buf);
    3918             : 
    3919           0 :                   break;
    3920             :                 }
    3921             :             }
    3922             : 
    3923           0 :           if (i < pk->numrevkeys)
    3924           0 :             continue;
    3925             :         }
    3926             : 
    3927           0 :       print_pubkey_info (NULL, revoker_pk);
    3928           0 :       print_fingerprint (NULL, revoker_pk, 2);
    3929           0 :       tty_printf ("\n");
    3930             : 
    3931           0 :       tty_printf (_("WARNING: appointing a key as a designated revoker "
    3932             :                     "cannot be undone!\n"));
    3933             : 
    3934           0 :       tty_printf ("\n");
    3935             : 
    3936           0 :       if (!cpr_get_answer_is_yes ("keyedit.add_revoker.okay",
    3937           0 :                                   _("Are you sure you want to appoint this "
    3938             :                                     "key as a designated revoker? (y/N) ")))
    3939           0 :         continue;
    3940             : 
    3941           0 :       free_public_key (revoker_pk);
    3942           0 :       revoker_pk = NULL;
    3943           0 :       break;
    3944           0 :     }
    3945             : 
    3946           0 :   rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
    3947             :                            keygen_add_revkey, &revkey, NULL);
    3948           0 :   if (rc)
    3949             :     {
    3950           0 :       write_status_error ("keysig", rc);
    3951           0 :       log_error ("signing failed: %s\n", gpg_strerror (rc));
    3952           0 :       goto fail;
    3953             :     }
    3954             : 
    3955             :   /* Insert into public keyblock.  */
    3956           0 :   pkt = xmalloc_clear (sizeof *pkt);
    3957           0 :   pkt->pkttype = PKT_SIGNATURE;
    3958           0 :   pkt->pkt.signature = sig;
    3959           0 :   insert_kbnode (pub_keyblock, new_kbnode (pkt), PKT_SIGNATURE);
    3960             : 
    3961           0 :   return 1;
    3962             : 
    3963             : fail:
    3964           0 :   if (sig)
    3965           0 :     free_seckey_enc (sig);
    3966           0 :   free_public_key (revoker_pk);
    3967             : 
    3968           0 :   return 0;
    3969             : }
    3970             : 
    3971             : 
    3972             : static int
    3973           0 : menu_expire (KBNODE pub_keyblock)
    3974             : {
    3975             :   int n1, signumber, rc;
    3976             :   u32 expiredate;
    3977           0 :   int mainkey = 0;
    3978             :   PKT_public_key *main_pk, *sub_pk;
    3979             :   PKT_user_id *uid;
    3980             :   KBNODE node;
    3981             :   u32 keyid[2];
    3982             : 
    3983           0 :   n1 = count_selected_keys (pub_keyblock);
    3984           0 :   if (n1 > 1)
    3985             :     {
    3986           0 :       tty_printf (_("Please select at most one subkey.\n"));
    3987           0 :       return 0;
    3988             :     }
    3989           0 :   else if (n1)
    3990           0 :     tty_printf (_("Changing expiration time for a subkey.\n"));
    3991             :   else
    3992             :     {
    3993           0 :       tty_printf (_("Changing expiration time for the primary key.\n"));
    3994           0 :       mainkey = 1;
    3995           0 :       no_primary_warning (pub_keyblock);
    3996             :     }
    3997             : 
    3998           0 :   expiredate = ask_expiredate ();
    3999             : 
    4000             :   /* Now we can actually change the self-signature(s) */
    4001           0 :   main_pk = sub_pk = NULL;
    4002           0 :   uid = NULL;
    4003           0 :   signumber = 0;
    4004           0 :   for (node = pub_keyblock; node; node = node->next)
    4005             :     {
    4006           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    4007             :         {
    4008           0 :           main_pk = node->pkt->pkt.public_key;
    4009           0 :           keyid_from_pk (main_pk, keyid);
    4010           0 :           main_pk->expiredate = expiredate;
    4011             :         }
    4012           0 :       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4013           0 :                && (node->flag & NODFLG_SELKEY))
    4014             :         {
    4015           0 :           sub_pk = node->pkt->pkt.public_key;
    4016           0 :           sub_pk->expiredate = expiredate;
    4017             :         }
    4018           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    4019           0 :         uid = node->pkt->pkt.user_id;
    4020           0 :       else if (main_pk && node->pkt->pkttype == PKT_SIGNATURE
    4021           0 :                && (mainkey || sub_pk))
    4022             :         {
    4023           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    4024           0 :           if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
    4025           0 :               && ((mainkey && uid
    4026           0 :                    && uid->created && (sig->sig_class & ~3) == 0x10)
    4027           0 :                   || (!mainkey && sig->sig_class == 0x18))
    4028           0 :               && sig->flags.chosen_selfsig)
    4029             :             {
    4030             :               /* This is a self-signature which is to be replaced.  */
    4031             :               PKT_signature *newsig;
    4032             :               PACKET *newpkt;
    4033             : 
    4034           0 :               signumber++;
    4035             : 
    4036           0 :               if ((mainkey && main_pk->version < 4)
    4037           0 :                   || (!mainkey && sub_pk->version < 4))
    4038             :                 {
    4039           0 :                   log_info
    4040           0 :                     (_("You can't change the expiration date of a v3 key\n"));
    4041           0 :                   return 0;
    4042             :                 }
    4043             : 
    4044           0 :               if (mainkey)
    4045           0 :                 rc = update_keysig_packet (&newsig, sig, main_pk, uid, NULL,
    4046             :                                            main_pk, keygen_add_key_expire,
    4047             :                                            main_pk);
    4048             :               else
    4049           0 :                 rc =
    4050           0 :                   update_keysig_packet (&newsig, sig, main_pk, NULL, sub_pk,
    4051             :                                         main_pk, keygen_add_key_expire, sub_pk);
    4052           0 :               if (rc)
    4053             :                 {
    4054           0 :                   log_error ("make_keysig_packet failed: %s\n",
    4055             :                              gpg_strerror (rc));
    4056           0 :                   return 0;
    4057             :                 }
    4058             : 
    4059             :               /* Replace the packet.  */
    4060           0 :               newpkt = xmalloc_clear (sizeof *newpkt);
    4061           0 :               newpkt->pkttype = PKT_SIGNATURE;
    4062           0 :               newpkt->pkt.signature = newsig;
    4063           0 :               free_packet (node->pkt);
    4064           0 :               xfree (node->pkt);
    4065           0 :               node->pkt = newpkt;
    4066           0 :               sub_pk = NULL;
    4067             :             }
    4068             :         }
    4069             :     }
    4070             : 
    4071           0 :   update_trust = 1;
    4072           0 :   return 1;
    4073             : }
    4074             : 
    4075             : 
    4076             : static int
    4077           0 : menu_backsign (KBNODE pub_keyblock)
    4078             : {
    4079           0 :   int rc, modified = 0;
    4080             :   PKT_public_key *main_pk;
    4081             :   KBNODE node;
    4082             :   u32 timestamp;
    4083             : 
    4084           0 :   assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
    4085             : 
    4086           0 :   merge_keys_and_selfsig (pub_keyblock);
    4087           0 :   main_pk = pub_keyblock->pkt->pkt.public_key;
    4088           0 :   keyid_from_pk (main_pk, NULL);
    4089             : 
    4090             :   /* We use the same timestamp for all backsigs so that we don't
    4091             :      reveal information about the used machine.  */
    4092           0 :   timestamp = make_timestamp ();
    4093             : 
    4094           0 :   for (node = pub_keyblock; node; node = node->next)
    4095             :     {
    4096           0 :       PKT_public_key *sub_pk = NULL;
    4097           0 :       KBNODE node2, sig_pk = NULL /*,sig_sk = NULL*/;
    4098             :       /* char *passphrase; */
    4099             : 
    4100             :       /* Find a signing subkey with no backsig */
    4101           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    4102             :         {
    4103           0 :           if (node->pkt->pkt.public_key->pubkey_usage & PUBKEY_USAGE_SIG)
    4104             :             {
    4105           0 :               if (node->pkt->pkt.public_key->flags.backsig)
    4106           0 :                 tty_printf (_
    4107             :                             ("signing subkey %s is already cross-certified\n"),
    4108           0 :                             keystr_from_pk (node->pkt->pkt.public_key));
    4109             :               else
    4110           0 :                 sub_pk = node->pkt->pkt.public_key;
    4111             :             }
    4112             :           else
    4113           0 :             tty_printf (_("subkey %s does not sign and so does"
    4114             :                           " not need to be cross-certified\n"),
    4115           0 :                         keystr_from_pk (node->pkt->pkt.public_key));
    4116             :         }
    4117             : 
    4118           0 :       if (!sub_pk)
    4119           0 :         continue;
    4120             : 
    4121             :       /* Find the selected selfsig on this subkey */
    4122           0 :       for (node2 = node->next;
    4123           0 :            node2 && node2->pkt->pkttype == PKT_SIGNATURE; node2 = node2->next)
    4124           0 :         if (node2->pkt->pkt.signature->version >= 4
    4125           0 :             && node2->pkt->pkt.signature->flags.chosen_selfsig)
    4126             :           {
    4127           0 :             sig_pk = node2;
    4128           0 :             break;
    4129             :           }
    4130             : 
    4131           0 :       if (!sig_pk)
    4132           0 :         continue;
    4133             : 
    4134             :       /* Find the secret subkey that matches the public subkey */
    4135           0 :       log_debug ("FIXME: Check whether a secret subkey is available.\n");
    4136             :       /* if (!sub_sk) */
    4137             :       /*   { */
    4138             :       /*     tty_printf (_("no secret subkey for public subkey %s - ignoring\n"), */
    4139             :       /*              keystr_from_pk (sub_pk)); */
    4140             :       /*     continue; */
    4141             :       /*   } */
    4142             : 
    4143             : 
    4144             :       /* Now we can get to work.  */
    4145             : 
    4146           0 :       rc = make_backsig (sig_pk->pkt->pkt.signature, main_pk, sub_pk, sub_pk,
    4147             :                          timestamp, NULL);
    4148           0 :       if (!rc)
    4149             :         {
    4150             :           PKT_signature *newsig;
    4151             :           PACKET *newpkt;
    4152             : 
    4153           0 :           rc = update_keysig_packet (&newsig, sig_pk->pkt->pkt.signature,
    4154             :                                      main_pk, NULL, sub_pk, main_pk,
    4155             :                                      NULL, NULL);
    4156           0 :           if (!rc)
    4157             :             {
    4158             :               /* Put the new sig into place on the pubkey */
    4159           0 :               newpkt = xmalloc_clear (sizeof (*newpkt));
    4160           0 :               newpkt->pkttype = PKT_SIGNATURE;
    4161           0 :               newpkt->pkt.signature = newsig;
    4162           0 :               free_packet (sig_pk->pkt);
    4163           0 :               xfree (sig_pk->pkt);
    4164           0 :               sig_pk->pkt = newpkt;
    4165             : 
    4166           0 :               modified = 1;
    4167             :             }
    4168             :           else
    4169             :             {
    4170           0 :               log_error ("update_keysig_packet failed: %s\n",
    4171             :                          gpg_strerror (rc));
    4172           0 :               break;
    4173             :             }
    4174             :         }
    4175             :       else
    4176             :         {
    4177           0 :           log_error ("make_backsig failed: %s\n", gpg_strerror (rc));
    4178           0 :           break;
    4179             :         }
    4180             :     }
    4181             : 
    4182           0 :   return modified;
    4183             : }
    4184             : 
    4185             : 
    4186             : static int
    4187           0 : change_primary_uid_cb (PKT_signature * sig, void *opaque)
    4188             : {
    4189             :   byte buf[1];
    4190             : 
    4191             :   /* first clear all primary uid flags so that we are sure none are
    4192             :    * lingering around */
    4193           0 :   delete_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID);
    4194           0 :   delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
    4195             : 
    4196             :   /* if opaque is set,we want to set the primary id */
    4197           0 :   if (opaque)
    4198             :     {
    4199           0 :       buf[0] = 1;
    4200           0 :       build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1);
    4201             :     }
    4202             : 
    4203           0 :   return 0;
    4204             : }
    4205             : 
    4206             : 
    4207             : /*
    4208             :  * Set the primary uid flag for the selected UID.  We will also reset
    4209             :  * all other primary uid flags.  For this to work with have to update
    4210             :  * all the signature timestamps.  If we would do this with the current
    4211             :  * time, we lose quite a lot of information, so we use a a kludge to
    4212             :  * do this: Just increment the timestamp by one second which is
    4213             :  * sufficient to updated a signature during import.
    4214             :  */
    4215             : static int
    4216           0 : menu_set_primary_uid (KBNODE pub_keyblock)
    4217             : {
    4218             :   PKT_public_key *main_pk;
    4219             :   PKT_user_id *uid;
    4220             :   KBNODE node;
    4221             :   u32 keyid[2];
    4222             :   int selected;
    4223           0 :   int attribute = 0;
    4224           0 :   int modified = 0;
    4225             : 
    4226           0 :   if (count_selected_uids (pub_keyblock) != 1)
    4227             :     {
    4228           0 :       tty_printf (_("Please select exactly one user ID.\n"));
    4229           0 :       return 0;
    4230             :     }
    4231             : 
    4232           0 :   main_pk = NULL;
    4233           0 :   uid = NULL;
    4234           0 :   selected = 0;
    4235             : 
    4236             :   /* Is our selected uid an attribute packet? */
    4237           0 :   for (node = pub_keyblock; node; node = node->next)
    4238           0 :     if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
    4239           0 :       attribute = (node->pkt->pkt.user_id->attrib_data != NULL);
    4240             : 
    4241           0 :   for (node = pub_keyblock; node; node = node->next)
    4242             :     {
    4243           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    4244           0 :         break; /* No more user ids expected - ready.  */
    4245             : 
    4246           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    4247             :         {
    4248           0 :           main_pk = node->pkt->pkt.public_key;
    4249           0 :           keyid_from_pk (main_pk, keyid);
    4250             :         }
    4251           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    4252             :         {
    4253           0 :           uid = node->pkt->pkt.user_id;
    4254           0 :           selected = node->flag & NODFLG_SELUID;
    4255             :         }
    4256           0 :       else if (main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE)
    4257             :         {
    4258           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    4259           0 :           if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
    4260           0 :               && (uid && (sig->sig_class & ~3) == 0x10)
    4261           0 :               && attribute == (uid->attrib_data != NULL)
    4262           0 :               && sig->flags.chosen_selfsig)
    4263             :             {
    4264           0 :               if (sig->version < 4)
    4265             :                 {
    4266           0 :                   char *user =
    4267           0 :                     utf8_to_native (uid->name, strlen (uid->name), 0);
    4268             : 
    4269           0 :                   log_info (_("skipping v3 self-signature on user ID \"%s\"\n"),
    4270             :                             user);
    4271           0 :                   xfree (user);
    4272             :                 }
    4273             :               else
    4274             :                 {
    4275             :                   /* This is a selfsignature which is to be replaced.
    4276             :                      We can just ignore v3 signatures because they are
    4277             :                      not able to carry the primary ID flag.  We also
    4278             :                      ignore self-sigs on user IDs that are not of the
    4279             :                      same type that we are making primary.  That is, if
    4280             :                      we are making a user ID primary, we alter user IDs.
    4281             :                      If we are making an attribute packet primary, we
    4282             :                      alter attribute packets. */
    4283             : 
    4284             :                   /* FIXME: We must make sure that we only have one
    4285             :                      self-signature per user ID here (not counting
    4286             :                      revocations) */
    4287             :                   PKT_signature *newsig;
    4288             :                   PACKET *newpkt;
    4289             :                   const byte *p;
    4290             :                   int action;
    4291             : 
    4292             :                   /* See whether this signature has the primary UID flag.  */
    4293           0 :                   p = parse_sig_subpkt (sig->hashed,
    4294             :                                         SIGSUBPKT_PRIMARY_UID, NULL);
    4295           0 :                   if (!p)
    4296           0 :                     p = parse_sig_subpkt (sig->unhashed,
    4297             :                                           SIGSUBPKT_PRIMARY_UID, NULL);
    4298           0 :                   if (p && *p)  /* yes */
    4299           0 :                     action = selected ? 0 : -1;
    4300             :                   else          /* no */
    4301           0 :                     action = selected ? 1 : 0;
    4302             : 
    4303           0 :                   if (action)
    4304             :                     {
    4305           0 :                       int rc = update_keysig_packet (&newsig, sig,
    4306             :                                                      main_pk, uid, NULL,
    4307             :                                                      main_pk,
    4308             :                                                      change_primary_uid_cb,
    4309             :                                                      action > 0 ? "x" : NULL);
    4310           0 :                       if (rc)
    4311             :                         {
    4312           0 :                           log_error ("update_keysig_packet failed: %s\n",
    4313             :                                      gpg_strerror (rc));
    4314           0 :                           return 0;
    4315             :                         }
    4316             :                       /* replace the packet */
    4317           0 :                       newpkt = xmalloc_clear (sizeof *newpkt);
    4318           0 :                       newpkt->pkttype = PKT_SIGNATURE;
    4319           0 :                       newpkt->pkt.signature = newsig;
    4320           0 :                       free_packet (node->pkt);
    4321           0 :                       xfree (node->pkt);
    4322           0 :                       node->pkt = newpkt;
    4323           0 :                       modified = 1;
    4324             :                     }
    4325             :                 }
    4326             :             }
    4327             :         }
    4328             :     }
    4329             : 
    4330           0 :   return modified;
    4331             : }
    4332             : 
    4333             : 
    4334             : /*
    4335             :  * Set preferences to new values for the selected user IDs
    4336             :  */
    4337             : static int
    4338           0 : menu_set_preferences (KBNODE pub_keyblock)
    4339             : {
    4340             :   PKT_public_key *main_pk;
    4341             :   PKT_user_id *uid;
    4342             :   KBNODE node;
    4343             :   u32 keyid[2];
    4344             :   int selected, select_all;
    4345           0 :   int modified = 0;
    4346             : 
    4347           0 :   no_primary_warning (pub_keyblock);
    4348             : 
    4349           0 :   select_all = !count_selected_uids (pub_keyblock);
    4350             : 
    4351             :   /* Now we can actually change the self signature(s) */
    4352           0 :   main_pk = NULL;
    4353           0 :   uid = NULL;
    4354           0 :   selected = 0;
    4355           0 :   for (node = pub_keyblock; node; node = node->next)
    4356             :     {
    4357           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    4358           0 :         break; /* No more user-ids expected - ready.  */
    4359             : 
    4360           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    4361             :         {
    4362           0 :           main_pk = node->pkt->pkt.public_key;
    4363           0 :           keyid_from_pk (main_pk, keyid);
    4364             :         }
    4365           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    4366             :         {
    4367           0 :           uid = node->pkt->pkt.user_id;
    4368           0 :           selected = select_all || (node->flag & NODFLG_SELUID);
    4369             :         }
    4370           0 :       else if (main_pk && uid && selected
    4371           0 :                && node->pkt->pkttype == PKT_SIGNATURE)
    4372             :         {
    4373           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    4374           0 :           if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
    4375           0 :               && (uid && (sig->sig_class & ~3) == 0x10)
    4376           0 :               && sig->flags.chosen_selfsig)
    4377             :             {
    4378           0 :               if (sig->version < 4)
    4379             :                 {
    4380           0 :                   char *user =
    4381           0 :                     utf8_to_native (uid->name, strlen (uid->name), 0);
    4382             : 
    4383           0 :                   log_info (_("skipping v3 self-signature on user ID \"%s\"\n"),
    4384             :                             user);
    4385           0 :                   xfree (user);
    4386             :                 }
    4387             :               else
    4388             :                 {
    4389             :                   /* This is a selfsignature which is to be replaced
    4390             :                    * We have to ignore v3 signatures because they are
    4391             :                    * not able to carry the preferences.  */
    4392             :                   PKT_signature *newsig;
    4393             :                   PACKET *newpkt;
    4394             :                   int rc;
    4395             : 
    4396           0 :                   rc = update_keysig_packet (&newsig, sig,
    4397             :                                              main_pk, uid, NULL, main_pk,
    4398             :                                              keygen_upd_std_prefs, NULL);
    4399           0 :                   if (rc)
    4400             :                     {
    4401           0 :                       log_error ("update_keysig_packet failed: %s\n",
    4402             :                                  gpg_strerror (rc));
    4403           0 :                       return 0;
    4404             :                     }
    4405             :                   /* replace the packet */
    4406           0 :                   newpkt = xmalloc_clear (sizeof *newpkt);
    4407           0 :                   newpkt->pkttype = PKT_SIGNATURE;
    4408           0 :                   newpkt->pkt.signature = newsig;
    4409           0 :                   free_packet (node->pkt);
    4410           0 :                   xfree (node->pkt);
    4411           0 :                   node->pkt = newpkt;
    4412           0 :                   modified = 1;
    4413             :                 }
    4414             :             }
    4415             :         }
    4416             :     }
    4417             : 
    4418           0 :   return modified;
    4419             : }
    4420             : 
    4421             : 
    4422             : static int
    4423           0 : menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
    4424             : {
    4425             :   PKT_public_key *main_pk;
    4426             :   PKT_user_id *uid;
    4427             :   KBNODE node;
    4428             :   u32 keyid[2];
    4429             :   int selected, select_all;
    4430           0 :   int modified = 0;
    4431             :   char *answer, *uri;
    4432             : 
    4433           0 :   no_primary_warning (pub_keyblock);
    4434             : 
    4435           0 :   if (url)
    4436           0 :     answer = xstrdup (url);
    4437             :   else
    4438             :     {
    4439           0 :       answer = cpr_get_utf8 ("keyedit.add_keyserver",
    4440           0 :                              _("Enter your preferred keyserver URL: "));
    4441           0 :       if (answer[0] == '\0' || answer[0] == CONTROL_D)
    4442             :         {
    4443           0 :           xfree (answer);
    4444           0 :           return 0;
    4445             :         }
    4446             :     }
    4447             : 
    4448           0 :   if (ascii_strcasecmp (answer, "none") == 0)
    4449           0 :     uri = NULL;
    4450             :   else
    4451             :     {
    4452           0 :       struct keyserver_spec *keyserver = NULL;
    4453             :       /* Sanity check the format */
    4454           0 :       keyserver = parse_keyserver_uri (answer, 1);
    4455           0 :       xfree (answer);
    4456           0 :       if (!keyserver)
    4457             :         {
    4458           0 :           log_info (_("could not parse keyserver URL\n"));
    4459           0 :           return 0;
    4460             :         }
    4461           0 :       uri = xstrdup (keyserver->uri);
    4462           0 :       free_keyserver_spec (keyserver);
    4463             :     }
    4464             : 
    4465           0 :   select_all = !count_selected_uids (pub_keyblock);
    4466             : 
    4467             :   /* Now we can actually change the self signature(s) */
    4468           0 :   main_pk = NULL;
    4469           0 :   uid = NULL;
    4470           0 :   selected = 0;
    4471           0 :   for (node = pub_keyblock; node; node = node->next)
    4472             :     {
    4473           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    4474           0 :         break; /* ready */
    4475             : 
    4476           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    4477             :         {
    4478           0 :           main_pk = node->pkt->pkt.public_key;
    4479           0 :           keyid_from_pk (main_pk, keyid);
    4480             :         }
    4481           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    4482             :         {
    4483           0 :           uid = node->pkt->pkt.user_id;
    4484           0 :           selected = select_all || (node->flag & NODFLG_SELUID);
    4485             :         }
    4486           0 :       else if (main_pk && uid && selected
    4487           0 :                && node->pkt->pkttype == PKT_SIGNATURE)
    4488             :         {
    4489           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    4490           0 :           if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
    4491           0 :               && (uid && (sig->sig_class & ~3) == 0x10)
    4492           0 :               && sig->flags.chosen_selfsig)
    4493             :             {
    4494           0 :               char *user = utf8_to_native (uid->name, strlen (uid->name), 0);
    4495           0 :               if (sig->version < 4)
    4496           0 :                 log_info (_("skipping v3 self-signature on user ID \"%s\"\n"),
    4497             :                           user);
    4498             :               else
    4499             :                 {
    4500             :                   /* This is a selfsignature which is to be replaced
    4501             :                    * We have to ignore v3 signatures because they are
    4502             :                    * not able to carry the subpacket. */
    4503             :                   PKT_signature *newsig;
    4504             :                   PACKET *newpkt;
    4505             :                   int rc;
    4506             :                   const byte *p;
    4507             :                   size_t plen;
    4508             : 
    4509           0 :                   p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &plen);
    4510           0 :                   if (p && plen)
    4511             :                     {
    4512           0 :                       tty_printf ("Current preferred keyserver for user"
    4513             :                                   " ID \"%s\": ", user);
    4514           0 :                       tty_print_utf8_string (p, plen);
    4515           0 :                       tty_printf ("\n");
    4516           0 :                       if (!cpr_get_answer_is_yes
    4517             :                           ("keyedit.confirm_keyserver",
    4518             :                            uri
    4519             :                            ? _("Are you sure you want to replace it? (y/N) ")
    4520             :                            : _("Are you sure you want to delete it? (y/N) ")))
    4521           0 :                         continue;
    4522             :                     }
    4523           0 :                   else if (uri == NULL)
    4524             :                     {
    4525             :                       /* There is no current keyserver URL, so there
    4526             :                          is no point in trying to un-set it. */
    4527           0 :                       continue;
    4528             :                     }
    4529             : 
    4530           0 :                   rc = update_keysig_packet (&newsig, sig,
    4531             :                                              main_pk, uid, NULL,
    4532             :                                              main_pk,
    4533             :                                              keygen_add_keyserver_url, uri);
    4534           0 :                   if (rc)
    4535             :                     {
    4536           0 :                       log_error ("update_keysig_packet failed: %s\n",
    4537             :                                  gpg_strerror (rc));
    4538           0 :                       xfree (uri);
    4539           0 :                       return 0;
    4540             :                     }
    4541             :                   /* replace the packet */
    4542           0 :                   newpkt = xmalloc_clear (sizeof *newpkt);
    4543           0 :                   newpkt->pkttype = PKT_SIGNATURE;
    4544           0 :                   newpkt->pkt.signature = newsig;
    4545           0 :                   free_packet (node->pkt);
    4546           0 :                   xfree (node->pkt);
    4547           0 :                   node->pkt = newpkt;
    4548           0 :                   modified = 1;
    4549             :                 }
    4550             : 
    4551           0 :               xfree (user);
    4552             :             }
    4553             :         }
    4554             :     }
    4555             : 
    4556           0 :   xfree (uri);
    4557           0 :   return modified;
    4558             : }
    4559             : 
    4560             : static int
    4561           0 : menu_set_notation (const char *string, KBNODE pub_keyblock)
    4562             : {
    4563             :   PKT_public_key *main_pk;
    4564             :   PKT_user_id *uid;
    4565             :   KBNODE node;
    4566             :   u32 keyid[2];
    4567             :   int selected, select_all;
    4568           0 :   int modified = 0;
    4569             :   char *answer;
    4570             :   struct notation *notation;
    4571             : 
    4572           0 :   no_primary_warning (pub_keyblock);
    4573             : 
    4574           0 :   if (string)
    4575           0 :     answer = xstrdup (string);
    4576             :   else
    4577             :     {
    4578           0 :       answer = cpr_get_utf8 ("keyedit.add_notation",
    4579           0 :                              _("Enter the notation: "));
    4580           0 :       if (answer[0] == '\0' || answer[0] == CONTROL_D)
    4581             :         {
    4582           0 :           xfree (answer);
    4583           0 :           return 0;
    4584             :         }
    4585             :     }
    4586             : 
    4587           0 :   if (!ascii_strcasecmp (answer, "none")
    4588           0 :       || !ascii_strcasecmp (answer, "-"))
    4589           0 :     notation = NULL; /* Delete them all.  */
    4590             :   else
    4591             :     {
    4592           0 :       notation = string_to_notation (answer, 0);
    4593           0 :       if (!notation)
    4594             :         {
    4595           0 :           xfree (answer);
    4596           0 :           return 0;
    4597             :         }
    4598             :     }
    4599             : 
    4600           0 :   xfree (answer);
    4601             : 
    4602           0 :   select_all = !count_selected_uids (pub_keyblock);
    4603             : 
    4604             :   /* Now we can actually change the self signature(s) */
    4605           0 :   main_pk = NULL;
    4606           0 :   uid = NULL;
    4607           0 :   selected = 0;
    4608           0 :   for (node = pub_keyblock; node; node = node->next)
    4609             :     {
    4610           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
    4611           0 :         break; /* ready */
    4612             : 
    4613           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    4614             :         {
    4615           0 :           main_pk = node->pkt->pkt.public_key;
    4616           0 :           keyid_from_pk (main_pk, keyid);
    4617             :         }
    4618           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    4619             :         {
    4620           0 :           uid = node->pkt->pkt.user_id;
    4621           0 :           selected = select_all || (node->flag & NODFLG_SELUID);
    4622             :         }
    4623           0 :       else if (main_pk && uid && selected
    4624           0 :                && node->pkt->pkttype == PKT_SIGNATURE)
    4625             :         {
    4626           0 :           PKT_signature *sig = node->pkt->pkt.signature;
    4627           0 :           if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
    4628           0 :               && (uid && (sig->sig_class & ~3) == 0x10)
    4629           0 :               && sig->flags.chosen_selfsig)
    4630             :             {
    4631           0 :               char *user = utf8_to_native (uid->name, strlen (uid->name), 0);
    4632           0 :               if (sig->version < 4)
    4633           0 :                 log_info (_("skipping v3 self-signature on user ID \"%s\"\n"),
    4634             :                           user);
    4635             :               else
    4636             :                 {
    4637             :                   PKT_signature *newsig;
    4638             :                   PACKET *newpkt;
    4639           0 :                   int rc, skip = 0, addonly = 1;
    4640             : 
    4641           0 :                   if (sig->flags.notation)
    4642             :                     {
    4643           0 :                       tty_printf ("Current notations for user ID \"%s\":\n",
    4644             :                                   user);
    4645           0 :                       tty_print_notations (-9, sig);
    4646             :                     }
    4647             :                   else
    4648             :                     {
    4649           0 :                       tty_printf ("No notations on user ID \"%s\"\n", user);
    4650           0 :                       if (notation == NULL)
    4651             :                         {
    4652             :                           /* There are no current notations, so there
    4653             :                              is no point in trying to un-set them. */
    4654           0 :                           continue;
    4655             :                         }
    4656             :                     }
    4657             : 
    4658           0 :                   if (notation)
    4659             :                     {
    4660             :                       struct notation *n;
    4661           0 :                       int deleting = 0;
    4662             : 
    4663           0 :                       notation->next = sig_to_notation (sig);
    4664             : 
    4665           0 :                       for (n = notation->next; n; n = n->next)
    4666           0 :                         if (strcmp (n->name, notation->name) == 0)
    4667             :                           {
    4668           0 :                             if (notation->value)
    4669             :                               {
    4670           0 :                                 if (strcmp (n->value, notation->value) == 0)
    4671             :                                   {
    4672           0 :                                     if (notation->flags.ignore)
    4673             :                                       {
    4674             :                                         /* Value match with a delete
    4675             :                                            flag. */
    4676           0 :                                         n->flags.ignore = 1;
    4677           0 :                                         deleting = 1;
    4678             :                                       }
    4679             :                                     else
    4680             :                                       {
    4681             :                                         /* Adding the same notation
    4682             :                                            twice, so don't add it at
    4683             :                                            all. */
    4684           0 :                                         skip = 1;
    4685           0 :                                         tty_printf ("Skipping notation:"
    4686             :                                                     " %s=%s\n",
    4687             :                                                     notation->name,
    4688             :                                                     notation->value);
    4689           0 :                                         break;
    4690             :                                       }
    4691             :                                   }
    4692             :                               }
    4693             :                             else
    4694             :                               {
    4695             :                                 /* No value, so it means delete. */
    4696           0 :                                 n->flags.ignore = 1;
    4697           0 :                                 deleting = 1;
    4698             :                               }
    4699             : 
    4700           0 :                             if (n->flags.ignore)
    4701             :                               {
    4702           0 :                                 tty_printf ("Removing notation: %s=%s\n",
    4703             :                                             n->name, n->value);
    4704           0 :                                 addonly = 0;
    4705             :                               }
    4706             :                           }
    4707             : 
    4708           0 :                       if (!notation->flags.ignore && !skip)
    4709           0 :                         tty_printf ("Adding notation: %s=%s\n",
    4710             :                                     notation->name, notation->value);
    4711             : 
    4712             :                       /* We tried to delete, but had no matches.  */
    4713           0 :                       if (notation->flags.ignore && !deleting)
    4714           0 :                         continue;
    4715             :                     }
    4716             :                   else
    4717             :                     {
    4718           0 :                       tty_printf ("Removing all notations\n");
    4719           0 :                       addonly = 0;
    4720             :                     }
    4721             : 
    4722           0 :                   if (skip
    4723           0 :                       || (!addonly
    4724           0 :                           &&
    4725           0 :                           !cpr_get_answer_is_yes ("keyedit.confirm_notation",
    4726           0 :                                                   _("Proceed? (y/N) "))))
    4727           0 :                     continue;
    4728             : 
    4729           0 :                   rc = update_keysig_packet (&newsig, sig,
    4730             :                                              main_pk, uid, NULL,
    4731             :                                              main_pk,
    4732             :                                              keygen_add_notations, notation);
    4733           0 :                   if (rc)
    4734             :                     {
    4735           0 :                       log_error ("update_keysig_packet failed: %s\n",
    4736             :                                  gpg_strerror (rc));
    4737           0 :                       free_notation (notation);
    4738           0 :                       xfree (user);
    4739           0 :                       return 0;
    4740             :                     }
    4741             : 
    4742             :                   /* replace the packet */
    4743           0 :                   newpkt = xmalloc_clear (sizeof *newpkt);
    4744           0 :                   newpkt->pkttype = PKT_SIGNATURE;
    4745           0 :                   newpkt->pkt.signature = newsig;
    4746           0 :                   free_packet (node->pkt);
    4747           0 :                   xfree (node->pkt);
    4748           0 :                   node->pkt = newpkt;
    4749           0 :                   modified = 1;
    4750             : 
    4751           0 :                   if (notation)
    4752             :                     {
    4753             :                       /* Snip off the notation list from the sig */
    4754           0 :                       free_notation (notation->next);
    4755           0 :                       notation->next = NULL;
    4756             :                     }
    4757             : 
    4758           0 :                   xfree (user);
    4759             :                 }
    4760             :             }
    4761             :         }
    4762             :     }
    4763             : 
    4764           0 :   free_notation (notation);
    4765           0 :   return modified;
    4766             : }
    4767             : 
    4768             : 
    4769             : /*
    4770             :  * Select one user id or remove all selection if IDX is 0 or select
    4771             :  * all if IDX is -1.  Returns: True if the selection changed.
    4772             :  */
    4773             : static int
    4774           0 : menu_select_uid (KBNODE keyblock, int idx)
    4775             : {
    4776             :   KBNODE node;
    4777             :   int i;
    4778             : 
    4779           0 :   if (idx == -1)                /* Select all. */
    4780             :     {
    4781           0 :       for (node = keyblock; node; node = node->next)
    4782           0 :         if (node->pkt->pkttype == PKT_USER_ID)
    4783           0 :           node->flag |= NODFLG_SELUID;
    4784           0 :       return 1;
    4785             :     }
    4786           0 :   else if (idx)                 /* Toggle.  */
    4787             :     {
    4788           0 :       for (i = 0, node = keyblock; node; node = node->next)
    4789             :         {
    4790           0 :           if (node->pkt->pkttype == PKT_USER_ID)
    4791           0 :             if (++i == idx)
    4792           0 :               break;
    4793             :         }
    4794           0 :       if (!node)
    4795             :         {
    4796           0 :           tty_printf (_("No user ID with index %d\n"), idx);
    4797           0 :           return 0;
    4798             :         }
    4799             : 
    4800           0 :       for (i = 0, node = keyblock; node; node = node->next)
    4801             :         {
    4802           0 :           if (node->pkt->pkttype == PKT_USER_ID)
    4803             :             {
    4804           0 :               if (++i == idx)
    4805             :                 {
    4806           0 :                   if ((node->flag & NODFLG_SELUID))
    4807           0 :                     node->flag &= ~NODFLG_SELUID;
    4808             :                   else
    4809           0 :                     node->flag |= NODFLG_SELUID;
    4810             :                 }
    4811             :             }
    4812             :         }
    4813             :     }
    4814             :   else                          /* Unselect all */
    4815             :     {
    4816           0 :       for (node = keyblock; node; node = node->next)
    4817           0 :         if (node->pkt->pkttype == PKT_USER_ID)
    4818           0 :           node->flag &= ~NODFLG_SELUID;
    4819             :     }
    4820             : 
    4821           0 :   return 1;
    4822             : }
    4823             : 
    4824             : 
    4825             : /* Search in the keyblock for a uid that matches namehash */
    4826             : static int
    4827           0 : menu_select_uid_namehash (KBNODE keyblock, const char *namehash)
    4828             : {
    4829             :   byte hash[NAMEHASH_LEN];
    4830             :   KBNODE node;
    4831             :   int i;
    4832             : 
    4833           0 :   assert (strlen (namehash) == NAMEHASH_LEN * 2);
    4834             : 
    4835           0 :   for (i = 0; i < NAMEHASH_LEN; i++)
    4836           0 :     hash[i] = hextobyte (&namehash[i * 2]);
    4837             : 
    4838           0 :   for (node = keyblock->next; node; node = node->next)
    4839             :     {
    4840           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    4841             :         {
    4842           0 :           namehash_from_uid (node->pkt->pkt.user_id);
    4843           0 :           if (memcmp (node->pkt->pkt.user_id->namehash, hash, NAMEHASH_LEN) ==
    4844             :               0)
    4845             :             {
    4846           0 :               if (node->flag & NODFLG_SELUID)
    4847           0 :                 node->flag &= ~NODFLG_SELUID;
    4848             :               else
    4849           0 :                 node->flag |= NODFLG_SELUID;
    4850             : 
    4851           0 :               break;
    4852             :             }
    4853             :         }
    4854             :     }
    4855             : 
    4856           0 :   if (!node)
    4857             :     {
    4858           0 :       tty_printf (_("No user ID with hash %s\n"), namehash);
    4859           0 :       return 0;
    4860             :     }
    4861             : 
    4862           0 :   return 1;
    4863             : }
    4864             : 
    4865             : 
    4866             : /*
    4867             :  * Select secondary keys
    4868             :  * Returns: True if the selection changed.
    4869             :  */
    4870             : static int
    4871           0 : menu_select_key (KBNODE keyblock, int idx)
    4872             : {
    4873             :   KBNODE node;
    4874             :   int i;
    4875             : 
    4876           0 :   if (idx == -1)                /* Select all.  */
    4877             :     {
    4878           0 :       for (node = keyblock; node; node = node->next)
    4879           0 :         if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4880           0 :             || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    4881           0 :           node->flag |= NODFLG_SELKEY;
    4882             :     }
    4883           0 :   else if (idx)                 /* Toggle selection.  */
    4884             :     {
    4885           0 :       for (i = 0, node = keyblock; node; node = node->next)
    4886             :         {
    4887           0 :           if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4888           0 :               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    4889           0 :             if (++i == idx)
    4890           0 :               break;
    4891             :         }
    4892           0 :       if (!node)
    4893             :         {
    4894           0 :           tty_printf (_("No subkey with index %d\n"), idx);
    4895           0 :           return 0;
    4896             :         }
    4897             : 
    4898           0 :       for (i = 0, node = keyblock; node; node = node->next)
    4899             :         {
    4900           0 :           if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4901           0 :               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    4902           0 :             if (++i == idx)
    4903             :               {
    4904           0 :                 if ((node->flag & NODFLG_SELKEY))
    4905           0 :                   node->flag &= ~NODFLG_SELKEY;
    4906             :                 else
    4907           0 :                   node->flag |= NODFLG_SELKEY;
    4908             :               }
    4909             :         }
    4910             :     }
    4911             :   else                          /* Unselect all. */
    4912             :     {
    4913           0 :       for (node = keyblock; node; node = node->next)
    4914           0 :         if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4915           0 :             || node->pkt->pkttype == PKT_SECRET_SUBKEY)
    4916           0 :           node->flag &= ~NODFLG_SELKEY;
    4917             :     }
    4918             : 
    4919           0 :   return 1;
    4920             : }
    4921             : 
    4922             : 
    4923             : static int
    4924           0 : count_uids_with_flag (KBNODE keyblock, unsigned flag)
    4925             : {
    4926             :   KBNODE node;
    4927           0 :   int i = 0;
    4928             : 
    4929           0 :   for (node = keyblock; node; node = node->next)
    4930           0 :     if (node->pkt->pkttype == PKT_USER_ID && (node->flag & flag))
    4931           0 :       i++;
    4932           0 :   return i;
    4933             : }
    4934             : 
    4935             : 
    4936             : static int
    4937           0 : count_keys_with_flag (KBNODE keyblock, unsigned flag)
    4938             : {
    4939             :   KBNODE node;
    4940           0 :   int i = 0;
    4941             : 
    4942           0 :   for (node = keyblock; node; node = node->next)
    4943           0 :     if ((node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    4944           0 :          || node->pkt->pkttype == PKT_SECRET_SUBKEY) && (node->flag & flag))
    4945           0 :       i++;
    4946           0 :   return i;
    4947             : }
    4948             : 
    4949             : 
    4950             : static int
    4951           0 : count_uids (KBNODE keyblock)
    4952             : {
    4953             :   KBNODE node;
    4954           0 :   int i = 0;
    4955             : 
    4956           0 :   for (node = keyblock; node; node = node->next)
    4957           0 :     if (node->pkt->pkttype == PKT_USER_ID)
    4958           0 :       i++;
    4959           0 :   return i;
    4960             : }
    4961             : 
    4962             : 
    4963             : /*
    4964             :  * Returns true if there is at least one selected user id
    4965             :  */
    4966             : static int
    4967           0 : count_selected_uids (KBNODE keyblock)
    4968             : {
    4969           0 :   return count_uids_with_flag (keyblock, NODFLG_SELUID);
    4970             : }
    4971             : 
    4972             : 
    4973             : static int
    4974           0 : count_selected_keys (KBNODE keyblock)
    4975             : {
    4976           0 :   return count_keys_with_flag (keyblock, NODFLG_SELKEY);
    4977             : }
    4978             : 
    4979             : 
    4980             : /* Returns how many real (i.e. not attribute) uids are unmarked.  */
    4981             : static int
    4982           0 : real_uids_left (KBNODE keyblock)
    4983             : {
    4984             :   KBNODE node;
    4985           0 :   int real = 0;
    4986             : 
    4987           0 :   for (node = keyblock; node; node = node->next)
    4988           0 :     if (node->pkt->pkttype == PKT_USER_ID && !(node->flag & NODFLG_SELUID) &&
    4989           0 :         !node->pkt->pkt.user_id->attrib_data)
    4990           0 :       real++;
    4991             : 
    4992           0 :   return real;
    4993             : }
    4994             : 
    4995             : 
    4996             : /*
    4997             :  * Ask whether the signature should be revoked.  If the user commits this,
    4998             :  * flag bit MARK_A is set on the signature and the user ID.
    4999             :  */
    5000             : static void
    5001           0 : ask_revoke_sig (KBNODE keyblock, KBNODE node)
    5002             : {
    5003           0 :   int doit = 0;
    5004             :   PKT_user_id *uid;
    5005           0 :   PKT_signature *sig = node->pkt->pkt.signature;
    5006           0 :   KBNODE unode = find_prev_kbnode (keyblock, node, PKT_USER_ID);
    5007             : 
    5008           0 :   if (!unode)
    5009             :     {
    5010           0 :       log_error ("Oops: no user ID for signature\n");
    5011           0 :       return;
    5012             :     }
    5013             : 
    5014           0 :   uid = unode->pkt->pkt.user_id;
    5015             : 
    5016           0 :   if (opt.with_colons)
    5017             :     {
    5018           0 :       if (uid->attrib_data)
    5019           0 :         printf ("uat:::::::::%u %lu", uid->numattribs, uid->attrib_len);
    5020             :       else
    5021             :         {
    5022           0 :           es_printf ("uid:::::::::");
    5023           0 :           es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
    5024             :         }
    5025             : 
    5026           0 :       es_printf ("\n");
    5027             : 
    5028           0 :       print_and_check_one_sig_colon (keyblock, node, NULL, NULL, NULL, NULL,
    5029             :                                      1);
    5030             :     }
    5031             :   else
    5032             :     {
    5033           0 :       char *p = utf8_to_native (unode->pkt->pkt.user_id->name,
    5034           0 :                                 unode->pkt->pkt.user_id->len, 0);
    5035           0 :       tty_printf (_("user ID: \"%s\"\n"), p);
    5036           0 :       xfree (p);
    5037             : 
    5038           0 :       tty_printf (_("signed by your key %s on %s%s%s\n"),
    5039           0 :                   keystr (sig->keyid), datestr_from_sig (sig),
    5040           0 :                   sig->flags.exportable ? "" : _(" (non-exportable)"), "");
    5041             :     }
    5042           0 :   if (sig->flags.expired)
    5043             :     {
    5044           0 :       tty_printf (_("This signature expired on %s.\n"),
    5045             :                   expirestr_from_sig (sig));
    5046             :       /* Use a different question so we can have different help text */
    5047           0 :       doit = cpr_get_answer_is_yes
    5048             :         ("ask_revoke_sig.expired",
    5049           0 :          _("Are you sure you still want to revoke it? (y/N) "));
    5050             :     }
    5051             :   else
    5052           0 :     doit = cpr_get_answer_is_yes
    5053             :       ("ask_revoke_sig.one",
    5054           0 :        _("Create a revocation certificate for this signature? (y/N) "));
    5055             : 
    5056           0 :   if (doit)
    5057             :     {
    5058           0 :       node->flag |= NODFLG_MARK_A;
    5059           0 :       unode->flag |= NODFLG_MARK_A;
    5060             :     }
    5061             : }
    5062             : 
    5063             : 
    5064             : /*
    5065             :  * Display all user ids of the current public key together with signatures
    5066             :  * done by one of our keys.  Then walk over all this sigs and ask the user
    5067             :  * whether he wants to revoke this signature.
    5068             :  * Return: True when the keyblock has changed.
    5069             :  */
    5070             : static int
    5071           0 : menu_revsig (KBNODE keyblock)
    5072             : {
    5073             :   PKT_signature *sig;
    5074             :   PKT_public_key *primary_pk;
    5075             :   KBNODE node;
    5076           0 :   int changed = 0;
    5077           0 :   int rc, any, skip = 1, all = !count_selected_uids (keyblock);
    5078           0 :   struct revocation_reason_info *reason = NULL;
    5079             : 
    5080           0 :   assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
    5081             : 
    5082             :   /* First check whether we have any signatures at all.  */
    5083           0 :   any = 0;
    5084           0 :   for (node = keyblock; node; node = node->next)
    5085             :     {
    5086           0 :       node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
    5087           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    5088             :         {
    5089           0 :           if (node->flag & NODFLG_SELUID || all)
    5090           0 :             skip = 0;
    5091             :           else
    5092           0 :             skip = 1;
    5093             :         }
    5094           0 :       else if (!skip && node->pkt->pkttype == PKT_SIGNATURE
    5095           0 :                && ((sig = node->pkt->pkt.signature),
    5096           0 :                    have_secret_key_with_kid (sig->keyid)))
    5097             :         {
    5098           0 :           if ((sig->sig_class & ~3) == 0x10)
    5099             :             {
    5100           0 :               any = 1;
    5101           0 :               break;
    5102             :             }
    5103             :         }
    5104             :     }
    5105             : 
    5106           0 :   if (!any)
    5107             :     {
    5108           0 :       tty_printf (_("Not signed by you.\n"));
    5109           0 :       return 0;
    5110             :     }
    5111             : 
    5112             : 
    5113             :   /* FIXME: detect duplicates here  */
    5114           0 :   tty_printf (_("You have signed these user IDs on key %s:\n"),
    5115           0 :               keystr_from_pk (keyblock->pkt->pkt.public_key));
    5116           0 :   for (node = keyblock; node; node = node->next)
    5117             :     {
    5118           0 :       node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
    5119           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    5120             :         {
    5121           0 :           if (node->flag & NODFLG_SELUID || all)
    5122           0 :             {
    5123           0 :               PKT_user_id *uid = node->pkt->pkt.user_id;
    5124             :               /* Hmmm: Should we show only UIDs with a signature? */
    5125           0 :               tty_printf ("     ");
    5126           0 :               tty_print_utf8_string (uid->name, uid->len);
    5127           0 :               tty_printf ("\n");
    5128           0 :               skip = 0;
    5129             :             }
    5130             :           else
    5131           0 :             skip = 1;
    5132             :         }
    5133           0 :       else if (!skip && node->pkt->pkttype == PKT_SIGNATURE
    5134           0 :                && ((sig = node->pkt->pkt.signature),
    5135           0 :                    have_secret_key_with_kid (sig->keyid)))
    5136             :         {
    5137           0 :           if ((sig->sig_class & ~3) == 0x10)
    5138             :             {
    5139           0 :               tty_printf ("   ");
    5140           0 :               tty_printf (_("signed by your key %s on %s%s%s\n"),
    5141           0 :                           keystr (sig->keyid), datestr_from_sig (sig),
    5142           0 :                           sig->flags.exportable ? "" : _(" (non-exportable)"),
    5143           0 :                           sig->flags.revocable ? "" : _(" (non-revocable)"));
    5144           0 :               if (sig->flags.revocable)
    5145           0 :                 node->flag |= NODFLG_SELSIG;
    5146             :             }
    5147           0 :           else if (sig->sig_class == 0x30)
    5148             :             {
    5149           0 :               tty_printf ("   ");
    5150           0 :               tty_printf (_("revoked by your key %s on %s\n"),
    5151           0 :                           keystr (sig->keyid), datestr_from_sig (sig));
    5152             :             }
    5153             :         }
    5154             :     }
    5155             : 
    5156           0 :   tty_printf ("\n");
    5157             : 
    5158             :   /* ask */
    5159           0 :   for (node = keyblock; node; node = node->next)
    5160             :     {
    5161           0 :       if (!(node->flag & NODFLG_SELSIG))
    5162           0 :         continue;
    5163           0 :       ask_revoke_sig (keyblock, node);
    5164             :     }
    5165             : 
    5166             :   /* present selected */
    5167           0 :   any = 0;
    5168           0 :   for (node = keyblock; node; node = node->next)
    5169             :     {
    5170           0 :       if (!(node->flag & NODFLG_MARK_A))
    5171           0 :         continue;
    5172           0 :       if (!any)
    5173             :         {
    5174           0 :           any = 1;
    5175           0 :           tty_printf (_("You are about to revoke these signatures:\n"));
    5176             :         }
    5177           0 :       if (node->pkt->pkttype == PKT_USER_ID)
    5178             :         {
    5179           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    5180           0 :           tty_printf ("     ");
    5181           0 :           tty_print_utf8_string (uid->name, uid->len);
    5182           0 :           tty_printf ("\n");
    5183             :         }
    5184           0 :       else if (node->pkt->pkttype == PKT_SIGNATURE)
    5185             :         {
    5186           0 :           sig = node->pkt->pkt.signature;
    5187           0 :           tty_printf ("   ");
    5188           0 :           tty_printf (_("signed by your key %s on %s%s%s\n"),
    5189           0 :                       keystr (sig->keyid), datestr_from_sig (sig), "",
    5190           0 :                       sig->flags.exportable ? "" : _(" (non-exportable)"));
    5191             :         }
    5192             :     }
    5193           0 :   if (!any)
    5194           0 :     return 0;                   /* none selected */
    5195             : 
    5196           0 :   if (!cpr_get_answer_is_yes
    5197             :       ("ask_revoke_sig.okay",
    5198           0 :        _("Really create the revocation certificates? (y/N) ")))
    5199           0 :     return 0;                   /* forget it */
    5200             : 
    5201           0 :   reason = ask_revocation_reason (0, 1, 0);
    5202           0 :   if (!reason)
    5203             :     {                           /* user decided to cancel */
    5204           0 :       return 0;
    5205             :     }
    5206             : 
    5207             :   /* now we can sign the user ids */
    5208             : reloop:                 /* (must use this, because we are modifing the list) */
    5209           0 :   primary_pk = keyblock->pkt->pkt.public_key;
    5210           0 :   for (node = keyblock; node; node = node->next)
    5211             :     {
    5212             :       KBNODE unode;
    5213             :       PACKET *pkt;
    5214             :       struct sign_attrib attrib;
    5215             :       PKT_public_key *signerkey;
    5216             : 
    5217           0 :       if (!(node->flag & NODFLG_MARK_A)
    5218           0 :           || node->pkt->pkttype != PKT_SIGNATURE)
    5219           0 :         continue;
    5220           0 :       unode = find_prev_kbnode (keyblock, node, PKT_USER_ID);
    5221           0 :       assert (unode);           /* we already checked this */
    5222             : 
    5223           0 :       memset (&attrib, 0, sizeof attrib);
    5224           0 :       attrib.reason = reason;
    5225           0 :       attrib.non_exportable = !node->pkt->pkt.signature->flags.exportable;
    5226             : 
    5227           0 :       node->flag &= ~NODFLG_MARK_A;
    5228           0 :       signerkey = xmalloc_secure_clear (sizeof *signerkey);
    5229           0 :       if (get_seckey (signerkey, node->pkt->pkt.signature->keyid))
    5230             :         {
    5231           0 :           log_info (_("no secret key\n"));
    5232           0 :           free_public_key (signerkey);
    5233           0 :           continue;
    5234             :         }
    5235           0 :       rc = make_keysig_packet (&sig, primary_pk,
    5236           0 :                                unode->pkt->pkt.user_id,
    5237             :                                NULL, signerkey, 0x30, 0, 0, 0,
    5238             :                                sign_mk_attrib, &attrib, NULL);
    5239           0 :       free_public_key (signerkey);
    5240           0 :       if (rc)
    5241             :         {
    5242           0 :           write_status_error ("keysig", rc);
    5243           0 :           log_error (_("signing failed: %s\n"), gpg_strerror (rc));
    5244           0 :           release_revocation_reason_info (reason);
    5245           0 :           return changed;
    5246             :         }
    5247           0 :       changed = 1;              /* we changed the keyblock */
    5248           0 :       update_trust = 1;
    5249             :       /* Are we revoking our own uid? */
    5250           0 :       if (primary_pk->keyid[0] == sig->keyid[0] &&
    5251           0 :           primary_pk->keyid[1] == sig->keyid[1])
    5252           0 :         unode->pkt->pkt.user_id->is_revoked = 1;
    5253           0 :       pkt = xmalloc_clear (sizeof *pkt);
    5254           0 :       pkt->pkttype = PKT_SIGNATURE;
    5255           0 :       pkt->pkt.signature = sig;
    5256           0 :       insert_kbnode (unode, new_kbnode (pkt), 0);
    5257           0 :       goto reloop;
    5258             :     }
    5259             : 
    5260           0 :   release_revocation_reason_info (reason);
    5261           0 :   return changed;
    5262             : }
    5263             : 
    5264             : 
    5265             : /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
    5266             :    keyblock changed.  */
    5267             : static int
    5268           0 : menu_revuid (KBNODE pub_keyblock)
    5269             : {
    5270           0 :   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
    5271             :   KBNODE node;
    5272           0 :   int changed = 0;
    5273             :   int rc;
    5274           0 :   struct revocation_reason_info *reason = NULL;
    5275             : 
    5276             :   /* Note that this is correct as per the RFCs, but nevertheless
    5277             :      somewhat meaningless in the real world.  1991 did define the 0x30
    5278             :      sig class, but PGP 2.x did not actually implement it, so it would
    5279             :      probably be safe to use v4 revocations everywhere. -ds */
    5280             : 
    5281           0 :   for (node = pub_keyblock; node; node = node->next)
    5282           0 :     if (pk->version > 3 || (node->pkt->pkttype == PKT_USER_ID &&
    5283           0 :                             node->pkt->pkt.user_id->selfsigversion > 3))
    5284             :       {
    5285           0 :         if ((reason = ask_revocation_reason (0, 1, 4)))
    5286           0 :           break;
    5287             :         else
    5288           0 :           goto leave;
    5289             :       }
    5290             : 
    5291             :  reloop: /* (better this way because we are modifing the keyring) */
    5292           0 :   for (node = pub_keyblock; node; node = node->next)
    5293           0 :     if (node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
    5294             :       {
    5295           0 :         PKT_user_id *uid = node->pkt->pkt.user_id;
    5296             : 
    5297           0 :         if (uid->is_revoked)
    5298             :           {
    5299           0 :             char *user = utf8_to_native (uid->name, uid->len, 0);
    5300           0 :             log_info (_("user ID \"%s\" is already revoked\n"), user);
    5301           0 :             xfree (user);
    5302             :           }
    5303             :         else
    5304             :           {
    5305             :             PACKET *pkt;
    5306             :             PKT_signature *sig;
    5307             :             struct sign_attrib attrib;
    5308           0 :             u32 timestamp = make_timestamp ();
    5309             : 
    5310           0 :             if (uid->created >= timestamp)
    5311             :               {
    5312             :                 /* Okay, this is a problem.  The user ID selfsig was
    5313             :                    created in the future, so we need to warn the user and
    5314             :                    set our revocation timestamp one second after that so
    5315             :                    everything comes out clean. */
    5316             : 
    5317           0 :                 log_info (_("WARNING: a user ID signature is dated %d"
    5318             :                             " seconds in the future\n"),
    5319           0 :                           uid->created - timestamp);
    5320             : 
    5321           0 :                 timestamp = uid->created + 1;
    5322             :               }
    5323             : 
    5324           0 :             memset (&attrib, 0, sizeof attrib);
    5325           0 :             attrib.reason = reason;
    5326             : 
    5327           0 :             node->flag &= ~NODFLG_SELUID;
    5328             : 
    5329           0 :             rc = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x30, 0,
    5330             :                                      timestamp, 0,
    5331             :                                      sign_mk_attrib, &attrib, NULL);
    5332           0 :             if (rc)
    5333             :               {
    5334           0 :                 write_status_error ("keysig", rc);
    5335           0 :                 log_error (_("signing failed: %s\n"), gpg_strerror (rc));
    5336           0 :                 goto leave;
    5337             :               }
    5338             :             else
    5339             :               {
    5340           0 :                 pkt = xmalloc_clear (sizeof *pkt);
    5341           0 :                 pkt->pkttype = PKT_SIGNATURE;
    5342           0 :                 pkt->pkt.signature = sig;
    5343           0 :                 insert_kbnode (node, new_kbnode (pkt), 0);
    5344             : 
    5345             : #ifndef NO_TRUST_MODELS
    5346             :                 /* If the trustdb has an entry for this key+uid then the
    5347             :                    trustdb needs an update. */
    5348           0 :                 if (!update_trust
    5349           0 :                     && (get_validity (pk, uid, NULL, 0) & TRUST_MASK) >=
    5350             :                     TRUST_UNDEFINED)
    5351           0 :                   update_trust = 1;
    5352             : #endif /*!NO_TRUST_MODELS*/
    5353             : 
    5354           0 :                 changed = 1;
    5355           0 :                 node->pkt->pkt.user_id->is_revoked = 1;
    5356             : 
    5357           0 :                 goto reloop;
    5358             :               }
    5359             :           }
    5360             :       }
    5361             : 
    5362           0 :   if (changed)
    5363           0 :     commit_kbnode (&pub_keyblock);
    5364             : 
    5365             : leave:
    5366           0 :   release_revocation_reason_info (reason);
    5367           0 :   return changed;
    5368             : }
    5369             : 
    5370             : 
    5371             : /*
    5372             :  * Revoke the whole key.
    5373             :  */
    5374             : static int
    5375           0 : menu_revkey (KBNODE pub_keyblock)
    5376             : {
    5377           0 :   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
    5378           0 :   int rc, changed = 0;
    5379             :   struct revocation_reason_info *reason;
    5380             :   PACKET *pkt;
    5381             :   PKT_signature *sig;
    5382             : 
    5383           0 :   if (pk->flags.revoked)
    5384             :     {
    5385           0 :       tty_printf (_("Key %s is already revoked.\n"), keystr_from_pk (pk));
    5386           0 :       return 0;
    5387             :     }
    5388             : 
    5389           0 :   reason = ask_revocation_reason (1, 0, 0);
    5390             :   /* user decided to cancel */
    5391           0 :   if (!reason)
    5392           0 :     return 0;
    5393             : 
    5394           0 :   rc = make_keysig_packet (&sig, pk, NULL, NULL, pk,
    5395             :                            0x20, 0, 0, 0,
    5396             :                            revocation_reason_build_cb, reason, NULL);
    5397           0 :   if (rc)
    5398             :     {
    5399           0 :       write_status_error ("keysig", rc);
    5400           0 :       log_error (_("signing failed: %s\n"), gpg_strerror (rc));
    5401           0 :       goto scram;
    5402             :     }
    5403             : 
    5404           0 :   changed = 1;                  /* we changed the keyblock */
    5405             : 
    5406           0 :   pkt = xmalloc_clear (sizeof *pkt);
    5407           0 :   pkt->pkttype = PKT_SIGNATURE;
    5408           0 :   pkt->pkt.signature = sig;
    5409           0 :   insert_kbnode (pub_keyblock, new_kbnode (pkt), 0);
    5410           0 :   commit_kbnode (&pub_keyblock);
    5411             : 
    5412           0 :   update_trust = 1;
    5413             : 
    5414             :  scram:
    5415           0 :   release_revocation_reason_info (reason);
    5416           0 :   return changed;
    5417             : }
    5418             : 
    5419             : 
    5420             : static int
    5421           0 : menu_revsubkey (KBNODE pub_keyblock)
    5422             : {
    5423             :   PKT_public_key *mainpk;
    5424             :   KBNODE node;
    5425           0 :   int changed = 0;
    5426             :   int rc;
    5427           0 :   struct revocation_reason_info *reason = NULL;
    5428             : 
    5429           0 :   reason = ask_revocation_reason (1, 0, 0);
    5430           0 :   if (!reason)
    5431           0 :       return 0; /* User decided to cancel.  */
    5432             : 
    5433             :  reloop: /* (better this way because we are modifing the keyring) */
    5434           0 :   mainpk = pub_keyblock->pkt->pkt.public_key;
    5435           0 :   for (node = pub_keyblock; node; node = node->next)
    5436             :     {
    5437           0 :       if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
    5438           0 :           && (node->flag & NODFLG_SELKEY))
    5439             :         {
    5440             :           PACKET *pkt;
    5441             :           PKT_signature *sig;
    5442           0 :           PKT_public_key *subpk = node->pkt->pkt.public_key;
    5443             :           struct sign_attrib attrib;
    5444             : 
    5445           0 :           if (subpk->flags.revoked)
    5446             :             {
    5447           0 :               tty_printf (_("Subkey %s is already revoked.\n"),
    5448             :                           keystr_from_pk (subpk));
    5449           0 :               continue;
    5450             :             }
    5451             : 
    5452           0 :           memset (&attrib, 0, sizeof attrib);
    5453           0 :           attrib.reason = reason;
    5454             : 
    5455           0 :           node->flag &= ~NODFLG_SELKEY;
    5456           0 :           rc = make_keysig_packet (&sig, mainpk, NULL, subpk, mainpk,
    5457             :                                    0x28, 0, 0, 0, sign_mk_attrib, &attrib,
    5458             :                                    NULL);
    5459           0 :           if (rc)
    5460             :             {
    5461           0 :               write_status_error ("keysig", rc);
    5462           0 :               log_error (_("signing failed: %s\n"), gpg_strerror (rc));
    5463           0 :               release_revocation_reason_info (reason);
    5464           0 :               return changed;
    5465             :             }
    5466           0 :           changed = 1;          /* we changed the keyblock */
    5467             : 
    5468           0 :           pkt = xmalloc_clear (sizeof *pkt);
    5469           0 :           pkt->pkttype = PKT_SIGNATURE;
    5470           0 :           pkt->pkt.signature = sig;
    5471           0 :           insert_kbnode (node, new_kbnode (pkt), 0);
    5472           0 :           goto reloop;
    5473             :         }
    5474             :     }
    5475           0 :   commit_kbnode (&pub_keyblock);
    5476             : 
    5477             :   /* No need to set update_trust here since signing keys no longer
    5478             :      are used to certify other keys, so there is no change in trust
    5479             :      when revoking/removing them */
    5480             : 
    5481           0 :   release_revocation_reason_info (reason);
    5482           0 :   return changed;
    5483             : }
    5484             : 
    5485             : 
    5486             : /* Note that update_ownertrust is going to mark the trustdb dirty when
    5487             :    enabling or disabling a key.  This is arguably sub-optimal as
    5488             :    disabled keys are still counted in the web of trust, but perhaps
    5489             :    not worth adding extra complexity to change. -ds */
    5490             : #ifndef NO_TRUST_MODELS
    5491             : static int
    5492           0 : enable_disable_key (KBNODE keyblock, int disable)
    5493             : {
    5494           0 :   PKT_public_key *pk =
    5495           0 :     find_kbnode (keyblock, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
    5496             :   unsigned int trust, newtrust;
    5497             : 
    5498           0 :   trust = newtrust = get_ownertrust (pk);
    5499           0 :   newtrust &= ~TRUST_FLAG_DISABLED;
    5500           0 :   if (disable)
    5501           0 :     newtrust |= TRUST_FLAG_DISABLED;
    5502           0 :   if (trust == newtrust)
    5503           0 :     return 0;                   /* already in that state */
    5504           0 :   update_ownertrust (pk, newtrust);
    5505           0 :   return 0;
    5506             : }
    5507             : #endif /*!NO_TRUST_MODELS*/
    5508             : 
    5509             : 
    5510             : static void
    5511           0 : menu_showphoto (KBNODE keyblock)
    5512             : {
    5513             :   KBNODE node;
    5514           0 :   int select_all = !count_selected_uids (keyblock);
    5515           0 :   int count = 0;
    5516           0 :   PKT_public_key *pk = NULL;
    5517             : 
    5518             :   /* Look for the public key first.  We have to be really, really,
    5519             :      explicit as to which photo this is, and what key it is a UID on
    5520             :      since people may want to sign it. */
    5521             : 
    5522           0 :   for (node = keyblock; node; node = node->next)
    5523             :     {
    5524           0 :       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
    5525           0 :         pk = node->pkt->pkt.public_key;
    5526           0 :       else if (node->pkt->pkttype == PKT_USER_ID)
    5527             :         {
    5528           0 :           PKT_user_id *uid = node->pkt->pkt.user_id;
    5529           0 :           count++;
    5530             : 
    5531           0 :           if ((select_all || (node->flag & NODFLG_SELUID)) &&
    5532           0 :               uid->attribs != NULL)
    5533             :             {
    5534             :               int i;
    5535             : 
    5536           0 :               for (i = 0; i < uid->numattribs; i++)
    5537             :                 {
    5538             :                   byte type;
    5539             :                   u32 size;
    5540             : 
    5541           0 :                   if (uid->attribs[i].type == ATTRIB_IMAGE &&
    5542           0 :                       parse_image_header (&uid->attribs[i], &type, &size))
    5543             :                     {
    5544           0 :                       tty_printf (_("Displaying %s photo ID of size %ld for "
    5545             :                                     "key %s (uid %d)\n"),
    5546             :                                   image_type_to_string (type, 1),
    5547             :                                   (ulong) size, keystr_from_pk (pk), count);
    5548           0 :                       show_photos (&uid->attribs[i], 1, pk, uid);
    5549             :                     }
    5550             :                 }
    5551             :             }
    5552             :         }
    5553             :     }
    5554           0 : }

Generated by: LCOV version 1.11