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

Generated by: LCOV version 1.11