* plaintext.c: Copyright.
[gnupg.git] / g10 / keyedit.c
1 /* keyedit.c - keyedit stuff
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2004 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <ctype.h>
29
30 #include "options.h"
31 #include "packet.h"
32 #include "errors.h"
33 #include "iobuf.h"
34 #include "keydb.h"
35 #include "memory.h"
36 #include "photoid.h"
37 #include "util.h"
38 #include "main.h"
39 #include "trustdb.h"
40 #include "filter.h"
41 #include "ttyio.h"
42 #include "status.h"
43 #include "i18n.h"
44
45 static void show_prefs( PKT_user_id *uid, int verbose );
46 static void show_key_with_all_names( KBNODE keyblock, int only_marked,
47             int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
48 static void show_key_and_fingerprint( KBNODE keyblock );
49 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
50 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
51 static int  menu_delsig( KBNODE pub_keyblock );
52 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
53 static int menu_addrevoker( KBNODE pub_keyblock,
54                             KBNODE sec_keyblock, int sensitive );
55 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
56 static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
57 static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
58 static int menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock );
59 static int menu_select_uid( KBNODE keyblock, int idx );
60 static int menu_select_key( KBNODE keyblock, int idx );
61 static int count_uids( KBNODE keyblock );
62 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
63 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
64 static int count_selected_uids( KBNODE keyblock );
65 static int real_uids_left( KBNODE keyblock );
66 static int count_selected_keys( KBNODE keyblock );
67 static int menu_revsig( KBNODE keyblock );
68 static int menu_revuid( KBNODE keyblock, KBNODE sec_keyblock );
69 static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
70 static int enable_disable_key( KBNODE keyblock, int disable );
71 static void menu_showphoto( KBNODE keyblock );
72
73 static int update_trust=0;
74
75 #define CONTROL_D ('D' - 'A' + 1)
76
77 #define NODFLG_BADSIG (1<<0)  /* bad signature */
78 #define NODFLG_NOKEY  (1<<1)  /* no public key */
79 #define NODFLG_SIGERR (1<<2)  /* other sig error */
80
81 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
82 #define NODFLG_DELSIG (1<<5)  /* to be deleted */
83
84 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
85 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
86 #define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
87
88 struct sign_attrib {
89     int non_exportable,non_revocable;
90     struct revocation_reason_info *reason;
91     byte trust_depth,trust_value;
92     char *trust_regexp;
93 };
94
95 /****************
96  * Print information about a signature, check it and return true
97  * if the signature is okay. NODE must be a signature packet.
98  */
99 static int
100 print_and_check_one_sig( KBNODE keyblock, KBNODE node,
101                          int *inv_sigs, int *no_key, int *oth_err,
102                         int *is_selfsig, int print_without_key )
103 {
104     PKT_signature *sig = node->pkt->pkt.signature;
105     int rc, sigrc;
106     int is_rev = sig->sig_class == 0x30;
107
108     /* TODO: Make sure a cached sig record here still has the pk that
109        issued it.  See also keylist.c:list_keyblock_print */
110
111     switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) {
112       case 0:
113         node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
114         sigrc = '!';
115         break;
116       case G10ERR_BAD_SIGN:
117         node->flag = NODFLG_BADSIG;
118         sigrc = '-';
119         if( inv_sigs )
120             ++*inv_sigs;
121         break;
122       case G10ERR_NO_PUBKEY:
123       case G10ERR_UNU_PUBKEY:
124         node->flag = NODFLG_NOKEY;
125         sigrc = '?';
126         if( no_key )
127             ++*no_key;
128         break;
129       default:
130         node->flag = NODFLG_SIGERR;
131         sigrc = '%';
132         if( oth_err )
133             ++*oth_err;
134         break;
135     }
136     if( sigrc != '?' || print_without_key ) {
137         tty_printf("%s%c%c %c%c%c%c%c%c ",
138                    is_rev? "rev":"sig",sigrc,
139                    (sig->sig_class-0x10>0 &&
140                     sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
141                    sig->flags.exportable?' ':'L',
142                    sig->flags.revocable?' ':'R',
143                    sig->flags.policy_url?'P':' ',
144                    sig->flags.notation?'N':' ',
145                    sig->flags.expired?'X':' ',
146                    (sig->trust_depth>9)?'T':
147                    (sig->trust_depth>0)?'0'+sig->trust_depth:' ');
148         if(opt.list_options&LIST_SHOW_LONG_KEYIDS)
149           tty_printf("%08lX%08lX",(ulong)sig->keyid[0],(ulong)sig->keyid[1]);
150         else
151           tty_printf("%08lX",(ulong)sig->keyid[1]);
152         tty_printf(" %s", datestr_from_sig(sig));
153         if(opt.list_options&LIST_SHOW_SIG_EXPIRE)
154           tty_printf(" %s",expirestr_from_sig(sig));
155         tty_printf("  ");
156         if( sigrc == '%' )
157             tty_printf("[%s] ", g10_errstr(rc) );
158         else if( sigrc == '?' )
159             ;
160         else if( *is_selfsig ) {
161             tty_printf( is_rev? _("[revocation]")
162                               : _("[self-signature]") );
163         }
164         else {
165             size_t n;
166             char *p = get_user_id( sig->keyid, &n );
167             tty_print_utf8_string2( p, n, opt.screen_columns-37 );
168             m_free(p);
169         }
170         tty_printf("\n");
171
172         if(sig->flags.policy_url && (opt.list_options&LIST_SHOW_POLICY_URLS))
173           show_policy_url(sig,3,0);
174
175         if(sig->flags.notation && (opt.list_options&LIST_SHOW_NOTATIONS))
176           show_notation(sig,3,0);
177
178         if(sig->flags.pref_ks && (opt.list_options&LIST_SHOW_KEYSERVER_URLS))
179           show_keyserver_url(sig,3,0);
180     }
181
182     return (sigrc == '!');
183 }
184
185
186
187 /****************
188  * Check the keysigs and set the flags to indicate errors.
189  * Returns true if error found.
190  */
191 static int
192 check_all_keysigs( KBNODE keyblock, int only_selected )
193 {
194     KBNODE kbctx;
195     KBNODE node;
196     int inv_sigs = 0;
197     int no_key = 0;
198     int oth_err = 0;
199     int has_selfsig = 0;
200     int mis_selfsig = 0;
201     int selected = !only_selected;
202     int anyuid = 0;
203
204     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
205         if( node->pkt->pkttype == PKT_USER_ID ) {
206             PKT_user_id *uid = node->pkt->pkt.user_id;
207
208             if( only_selected )
209                 selected = (node->flag & NODFLG_SELUID);
210             if( selected ) {
211                 tty_printf("uid  ");
212                 tty_print_utf8_string( uid->name, uid->len );
213                 tty_printf("\n");
214                 if( anyuid && !has_selfsig )
215                     mis_selfsig++;
216                 has_selfsig = 0;
217                 anyuid = 1;
218             }
219         }
220         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
221                  && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
222                      || node->pkt->pkt.signature->sig_class == 0x30 )  ) {
223             int selfsig;
224
225             if( print_and_check_one_sig( keyblock, node, &inv_sigs,
226                                         &no_key, &oth_err, &selfsig, 0 ) ) {
227                 if( selfsig )
228                     has_selfsig = 1;
229             }
230             /* Hmmm: should we update the trustdb here? */
231         }
232     }
233     if( !has_selfsig )
234         mis_selfsig++;
235     if( inv_sigs == 1 )
236         tty_printf(_("1 bad signature\n") );
237     else if( inv_sigs )
238         tty_printf(_("%d bad signatures\n"), inv_sigs );
239     if( no_key == 1 )
240         tty_printf(_("1 signature not checked due to a missing key\n") );
241     else if( no_key )
242         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
243     if( oth_err == 1 )
244         tty_printf(_("1 signature not checked due to an error\n") );
245     else if( oth_err )
246         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
247     if( mis_selfsig == 1 )
248         tty_printf(_("1 user ID without valid self-signature detected\n"));
249     else if( mis_selfsig  )
250         tty_printf(_("%d user IDs without valid self-signatures detected\n"),
251                                                                     mis_selfsig);
252
253     return inv_sigs || no_key || oth_err || mis_selfsig;
254 }
255
256
257
258
259 static int
260 sign_mk_attrib( PKT_signature *sig, void *opaque )
261 {
262     struct sign_attrib *attrib = opaque;
263     byte buf[8];
264
265     if( attrib->non_exportable ) {
266         buf[0] = 0; /* not exportable */
267         build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
268     }
269
270     if( attrib->non_revocable ) {
271         buf[0] = 0; /* not revocable */
272         build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 );
273     }
274
275     if( attrib->reason )
276         revocation_reason_build_cb( sig, attrib->reason );
277
278     if(attrib->trust_depth)
279       {
280         /* Not critical.  If someone doesn't understand trust sigs,
281            this can still be a valid regular signature. */
282         buf[0] = attrib->trust_depth;
283         buf[1] = attrib->trust_value;
284         build_sig_subpkt(sig,SIGSUBPKT_TRUST,buf,2);
285
286         /* Critical.  If someone doesn't understands regexps, this
287            whole sig should be invalid.  Note the +1 for the length -
288            regexps are null terminated. */
289         if(attrib->trust_regexp)
290           build_sig_subpkt(sig,SIGSUBPKT_FLAG_CRITICAL|SIGSUBPKT_REGEXP,
291                            attrib->trust_regexp,
292                            strlen(attrib->trust_regexp)+1);
293       }
294
295     return 0;
296 }
297
298 static void
299 trustsig_prompt(byte *trust_value,byte *trust_depth,char **regexp)
300 {
301   char *p;
302
303   *trust_value=0;
304   *trust_depth=0;
305   *regexp=NULL;
306
307   tty_printf("\n");
308   /* Same string as pkclist.c:do_edit_ownertrust */
309   tty_printf(_(
310                "Please decide how far you trust this user to correctly\n"
311                "verify other users' keys (by looking at passports,\n"
312                "checking fingerprints from different sources...)?\n\n"));
313   tty_printf (_("   (%d) I trust marginally\n"), 1);
314   tty_printf (_("   (%d) I trust fully\n"), 2);
315   tty_printf("\n");
316
317   while(*trust_value==0)
318     {
319       p = cpr_get("trustsig_prompt.trust_value",_("Your selection? "));
320       trim_spaces(p);
321       cpr_kill_prompt();
322       /* 60 and 120 are as per RFC2440 */
323       if(p[0]=='1' && !p[1])
324         *trust_value=60;
325       else if(p[0]=='2' && !p[1])
326         *trust_value=120;
327       m_free(p);
328     }
329
330   tty_printf("\n");
331
332   tty_printf(_(
333               "Please enter the depth of this trust signature.\n"
334               "A depth greater than 1 allows the key you are signing to make\n"
335               "trust signatures on your behalf.\n"));
336   tty_printf("\n");
337
338   while(*trust_depth==0)
339     {
340       p = cpr_get("trustsig_prompt.trust_depth",_("Your selection? "));
341       trim_spaces(p);
342       cpr_kill_prompt();
343       *trust_depth=atoi(p);
344       m_free(p);
345       if(*trust_depth<1 || *trust_depth>255)
346         *trust_depth=0;
347     }
348
349   tty_printf("\n");
350
351   tty_printf(_("Please enter a domain to restrict this signature, "
352                "or enter for none.\n"));
353
354   tty_printf("\n");
355
356   p=cpr_get("trustsig_prompt.trust_regexp",_("Your selection? "));
357   trim_spaces(p);
358   cpr_kill_prompt();
359
360   if(strlen(p)>0)
361     {
362       char *q=p;
363       int regexplen=100,ind;
364
365       *regexp=m_alloc(regexplen);
366
367       /* Now mangle the domain the user entered into a regexp.  To do
368          this, \-escape everything that isn't alphanumeric, and attach
369          "<[^>]+[@.]" to the front, and ">$" to the end. */
370
371       strcpy(*regexp,"<[^>]+[@.]");
372       ind=strlen(*regexp);
373
374       while(*q)
375         {
376           if(!((*q>='A' && *q<='Z')
377                || (*q>='a' && *q<='z') || (*q>='0' && *q<='9')))
378             (*regexp)[ind++]='\\';
379
380           (*regexp)[ind++]=*q;
381
382           if((regexplen-ind)<3)
383             {
384               regexplen+=100;
385               *regexp=m_realloc(*regexp,regexplen);
386             }
387
388           q++;
389         }
390
391       (*regexp)[ind]='\0';
392       strcat(*regexp,">$");
393     }
394
395   m_free(p);
396   tty_printf("\n");
397 }
398
399 /****************
400  * Loop over all locusr and and sign the uids after asking.
401  * If no user id is marked, all user ids will be signed;
402  * if some user_ids are marked those will be signed.
403  */
404 static int
405 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
406            int local, int nonrevocable, int trust )
407 {
408     int rc = 0;
409     SK_LIST sk_list = NULL;
410     SK_LIST sk_rover = NULL;
411     PKT_secret_key *sk = NULL;
412     KBNODE node, uidnode;
413     PKT_public_key *primary_pk=NULL;
414     int select_all = !count_selected_uids(keyblock);
415     int all_v3=1;
416
417     /* Are there any non-v3 sigs on this key already? */
418     if(PGP2)
419       for(node=keyblock;node;node=node->next)
420         if(node->pkt->pkttype==PKT_SIGNATURE &&
421            node->pkt->pkt.signature->version>3)
422           {
423             all_v3=0;
424             break;
425           }
426
427     /* build a list of all signators.
428      *    
429      * We use the CERT flag to request the primary which must always
430      * be one which is capable of signing keys.  I can't see a reason
431      * why to sign keys using a subkey.  Implementation of USAGE_CERT
432      * is just a hack in getkey.c and does not mean that a subkey
433      * marked as certification capable will be used */
434     rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT);
435     if( rc )
436         goto leave;
437
438     /* loop over all signators */
439     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
440         u32 sk_keyid[2],pk_keyid[2];
441         size_t n;
442         char *p,*trust_regexp=NULL;
443         int force_v4=0,class=0,selfsig=0;
444         u32 duration=0,timestamp=0;
445         byte trust_depth=0,trust_value=0;
446
447         if(local || nonrevocable || trust ||
448            opt.cert_policy_url || opt.cert_notation_data)
449           force_v4=1;
450
451         /* we have to use a copy of the sk, because make_keysig_packet
452          * may remove the protection from sk and if we did other
453          * changes to the secret key, we would save the unprotected
454          * version */
455         if( sk )
456             free_secret_key(sk);
457         sk = copy_secret_key( NULL, sk_rover->sk );
458         keyid_from_sk( sk, sk_keyid );
459         /* set mark A for all selected user ids */
460         for( node=keyblock; node; node = node->next ) {
461             if( select_all || (node->flag & NODFLG_SELUID) )
462                 node->flag |= NODFLG_MARK_A;
463             else
464                 node->flag &= ~NODFLG_MARK_A;
465         }
466         /* reset mark for uids which are already signed */
467         uidnode = NULL;
468         for( node=keyblock; node; node = node->next ) {
469             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
470                 primary_pk=node->pkt->pkt.public_key;
471                 keyid_from_pk( primary_pk, pk_keyid );
472
473                 /* Is this a self-sig? */
474                 if(pk_keyid[0]==sk_keyid[0] && pk_keyid[1]==sk_keyid[1])
475                   {
476                     selfsig=1;
477                     /* Do not force a v4 sig here, otherwise it would
478                        be difficult to remake a v3 selfsig.  If this
479                        is a v3->v4 promotion case, then we set
480                        force_v4 later anyway. */
481                     force_v4=0;
482                   }
483             }
484             else if( node->pkt->pkttype == PKT_USER_ID ) {
485                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
486                 if(uidnode)
487                   {
488                     char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
489                                               uidnode->pkt->pkt.user_id->len,
490                                               0);
491
492                     if(uidnode->pkt->pkt.user_id->is_revoked)
493                       {
494                         tty_printf(_("User ID \"%s\" is revoked."),user);
495
496                         if(opt.expert)
497                           {
498                             tty_printf("\n");
499                             /* No, so remove the mark and continue */
500                             if(!cpr_get_answer_is_yes("sign_uid.revoke_okay",
501                                                       _("Are you sure you "
502                                                         "still want to sign "
503                                                         "it? (y/N) ")))
504                               uidnode->flag &= ~NODFLG_MARK_A;
505                           }
506                         else
507                           {
508                             uidnode->flag &= ~NODFLG_MARK_A;
509                             tty_printf(_("  Unable to sign.\n"));
510                           }
511                       }
512                     else if(uidnode->pkt->pkt.user_id->is_expired)
513                       {
514                         tty_printf(_("User ID \"%s\" is expired."),user);
515
516                         if(opt.expert)
517                           {
518                             tty_printf("\n");
519                             /* No, so remove the mark and continue */
520                             if(!cpr_get_answer_is_yes("sign_uid.expire_okay",
521                                                       _("Are you sure you "
522                                                         "still want to sign "
523                                                         "it? (y/N) ")))
524                               uidnode->flag &= ~NODFLG_MARK_A;
525                           }
526                         else
527                           {
528                             uidnode->flag &= ~NODFLG_MARK_A;
529                             tty_printf(_("  Unable to sign.\n"));
530                           }
531                       }
532                     else if(!uidnode->pkt->pkt.user_id->created && !selfsig)
533                       {
534                         tty_printf(_("User ID \"%s\" is not self-signed."),
535                                    user);
536
537                         if(opt.expert)
538                           {
539                             tty_printf("\n");
540                             /* No, so remove the mark and continue */
541                             if(!cpr_get_answer_is_yes("sign_uid.nosig_okay",
542                                                       _("Are you sure you "
543                                                         "still want to sign "
544                                                         "it? (y/N) ")))
545                               uidnode->flag &= ~NODFLG_MARK_A;
546                           }
547                         else
548                           {
549                             uidnode->flag &= ~NODFLG_MARK_A;
550                             tty_printf(_("  Unable to sign.\n"));
551                           }
552                       }
553
554                     m_free(user);
555                   }
556             }
557             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
558                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
559                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
560                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
561                     char buf[50];
562                     char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
563                                               uidnode->pkt->pkt.user_id->len,
564                                               0);
565
566                     /* It's a v3 self-sig.  Make it into a v4 self-sig? */
567                     if(node->pkt->pkt.signature->version<4 && selfsig)
568                       {
569                         tty_printf(_("The self-signature on \"%s\"\n"
570                                      "is a PGP 2.x-style signature.\n"),user);
571  
572                         /* Note that the regular PGP2 warning below
573                            still applies if there are no v4 sigs on
574                            this key at all. */
575
576                         if(opt.expert)
577                           if(cpr_get_answer_is_yes("sign_uid.v4_promote_okay",
578                                                    _("Do you want to promote "
579                                                      "it to an OpenPGP self-"
580                                                      "signature? (y/N) ")))
581                             {
582                               force_v4=1;
583                               node->flag|=NODFLG_DELSIG;
584                               m_free(user);
585                               continue;
586                             }
587                       }
588
589                     /* Is the current signature expired? */
590                     if(node->pkt->pkt.signature->flags.expired)
591                       {
592                         tty_printf(_("Your current signature on \"%s\"\n"
593                                      "has expired.\n"),user);
594
595                         if(cpr_get_answer_is_yes("sign_uid.replace_expired_okay",
596                                                  _("Do you want to issue a "
597                                                    "new signature to replace "
598                                                    "the expired one? (y/N) ")))
599                           {
600                             /* Mark these for later deletion.  We
601                                don't want to delete them here, just in
602                                case the replacement signature doesn't
603                                happen for some reason.  We only delete
604                                these after the replacement is already
605                                in place. */
606
607                             node->flag|=NODFLG_DELSIG;
608                             m_free(user);
609                             continue;
610                           }
611                       }
612
613                     if(!node->pkt->pkt.signature->flags.exportable && !local)
614                       {
615                         /* It's a local sig, and we want to make a
616                            exportable sig. */
617                         tty_printf(_("Your current signature on \"%s\"\n"
618                                      "is a local signature.\n"),user);
619
620                         if(cpr_get_answer_is_yes("sign_uid.local_promote_okay",
621                                                  _("Do you want to promote "
622                                                    "it to a full exportable "
623                                                    "signature? (y/N) ")))
624                           {
625                             /* Mark these for later deletion.  We
626                                don't want to delete them here, just in
627                                case the replacement signature doesn't
628                                happen for some reason.  We only delete
629                                these after the replacement is already
630                                in place. */
631
632                             node->flag|=NODFLG_DELSIG;
633                             m_free(user);
634                             continue;
635                           }
636                       }
637
638                     /* Fixme: see whether there is a revocation in which
639                      * case we should allow to sign it again. */
640                     if (!node->pkt->pkt.signature->flags.exportable && local)
641                       tty_printf(_(
642                          "\"%s\" was already locally signed by key %08lX\n"),
643                                  user,(ulong)sk_keyid[1] );
644                     else
645                       tty_printf(_(
646                          "\"%s\" was already signed by key %08lX\n"),
647                                  user,(ulong)sk_keyid[1] );
648
649                     if(opt.expert
650                        && cpr_get_answer_is_yes("sign_uid.dupe_okay",
651                                                 _("Do you want to sign it "
652                                                   "again anyway? (y/N) ")))
653                       {
654                         /* Don't delete the old sig here since this is
655                            an --expert thing. */
656                         m_free(user);
657                         continue;
658                       }
659
660                     sprintf (buf, "%08lX%08lX",
661                              (ulong)sk->keyid[0], (ulong)sk->keyid[1] );
662                     write_status_text (STATUS_ALREADY_SIGNED, buf);
663                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
664
665                     m_free(user);
666                 }
667             }
668         }
669         /* check whether any uids are left for signing */
670         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
671             tty_printf(_("Nothing to sign with key %08lX\n"),
672                                                   (ulong)sk_keyid[1] );
673             continue;
674         }
675         /* Ask whether we really should sign these user id(s) */
676         tty_printf("\n");
677         show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 );
678         tty_printf("\n");
679
680         if(primary_pk->expiredate && !selfsig)
681           {
682             u32 now=make_timestamp();
683
684             if(primary_pk->expiredate<=now)
685               {
686                 tty_printf(_("This key has expired!"));
687
688                 if(opt.expert)
689                   {
690                     tty_printf("  ");
691                     if(!cpr_get_answer_is_yes("sign_uid.expired_okay",
692                                               _("Are you sure you still "
693                                                 "want to sign it? (y/N) ")))
694                       continue;
695                   }
696                 else
697                   {
698                     tty_printf(_("  Unable to sign.\n"));
699                     continue;
700                   }
701               }
702             else
703               {
704                 char *answer;
705
706                 tty_printf(_("This key is due to expire on %s.\n"),
707                            expirestr_from_pk(primary_pk));
708
709                 answer=cpr_get("sign_uid.expire",
710                                _("Do you want your signature to "
711                                  "expire at the same time? (Y/n) "));
712                 if(answer_is_yes_no_default(answer,1))
713                   {
714                     /* This fixes the signature timestamp we're going
715                        to make as now.  This is so the expiration date
716                        is exactly correct, and not a few seconds off
717                        (due to the time it takes to answer the
718                        questions, enter the passphrase, etc). */
719                     timestamp=now;
720                     duration=primary_pk->expiredate-now;
721                     force_v4=1;
722                   }
723
724                 cpr_kill_prompt();
725                 m_free(answer);
726               }
727           }
728
729         /* Only ask for duration if we haven't already set it to match
730            the expiration of the pk */
731         if(opt.ask_cert_expire && !duration && !selfsig)
732           duration=ask_expire_interval(1);
733
734         if(duration)
735           force_v4=1;
736
737         /* Is --pgp2 on, it's a v3 key, all the sigs on the key are
738            currently v3 and we're about to sign it with a v4 sig?  If
739            so, danger! */
740         if(PGP2 && all_v3 &&
741            (sk->version>3 || force_v4) && primary_pk->version<=3)
742           {
743             tty_printf(_("You may not make an OpenPGP signature on a "
744                          "PGP 2.x key while in --pgp2 mode.\n"));
745             tty_printf(_("This would make the key unusable in PGP 2.x.\n"));
746
747             if(opt.expert)
748               {
749                 if(!cpr_get_answer_is_yes("sign_uid.v4_on_v3_okay",
750                                           _("Are you sure you still "
751                                             "want to sign it? (y/N) ")))
752                   continue;
753
754                 all_v3=0;
755               }
756             else
757               continue;
758           }
759
760         if(selfsig)
761           ;
762         else
763           {
764             if(opt.batch || !opt.ask_cert_level)
765               class=0x10+opt.def_cert_level;
766             else
767               {
768                 char *answer;
769
770                 tty_printf(_("How carefully have you verified the key you are "
771                              "about to sign actually belongs\nto the person "
772                              "named above?  If you don't know what to "
773                              "answer, enter \"0\".\n"));
774                 tty_printf("\n");
775                 tty_printf(_("   (0) I will not answer.%s\n"),
776                            opt.def_cert_level==0?" (default)":"");
777                 tty_printf(_("   (1) I have not checked at all.%s\n"),
778                            opt.def_cert_level==1?" (default)":"");
779                 tty_printf(_("   (2) I have done casual checking.%s\n"),
780                            opt.def_cert_level==2?" (default)":"");
781                 tty_printf(_("   (3) I have done very careful checking.%s\n"),
782                            opt.def_cert_level==3?" (default)":"");
783                 tty_printf("\n");
784
785                 while(class==0)
786                   {
787                     answer = cpr_get("sign_uid.class",_("Your selection? "
788                                         "(enter '?' for more information): "));
789                     if(answer[0]=='\0')
790                       class=0x10+opt.def_cert_level; /* Default */
791                     else if(ascii_strcasecmp(answer,"0")==0)
792                       class=0x10; /* Generic */
793                     else if(ascii_strcasecmp(answer,"1")==0)
794                       class=0x11; /* Persona */
795                     else if(ascii_strcasecmp(answer,"2")==0)
796                       class=0x12; /* Casual */
797                     else if(ascii_strcasecmp(answer,"3")==0)
798                       class=0x13; /* Positive */
799                     else
800                       tty_printf(_("Invalid selection.\n"));
801
802                     m_free(answer);
803                   }
804               }
805
806             if(trust)
807               trustsig_prompt(&trust_value,&trust_depth,&trust_regexp);
808           }
809
810         tty_printf(_("Are you really sure that you want to sign this key\n"
811                      "with your key: \""));
812         p = get_user_id( sk_keyid, &n );
813         tty_print_utf8_string( p, n );
814         m_free(p); p = NULL;
815         tty_printf("\" (%08lX)\n",(ulong)sk_keyid[1]);
816
817         if(selfsig)
818           {
819             tty_printf(_("\nThis will be a self-signature.\n"));
820
821             if( local )
822               tty_printf(
823                          _("\nWARNING: the signature will not be marked "
824                            "as non-exportable.\n"));
825
826             if( nonrevocable )
827               tty_printf(
828                          _("\nWARNING: the signature will not be marked "
829                            "as non-revocable.\n"));
830           }
831         else
832           {
833             if( local )
834               tty_printf(
835                      _("\nThe signature will be marked as non-exportable.\n"));
836
837             if( nonrevocable )
838               tty_printf(
839                       _("\nThe signature will be marked as non-revocable.\n"));
840
841             switch(class)
842               {
843               case 0x11:
844                 tty_printf(_("\nI have not checked this key at all.\n"));
845                 break;
846
847               case 0x12:
848                 tty_printf(_("\nI have checked this key casually.\n"));
849                 break;
850
851               case 0x13:
852                 tty_printf(_("\nI have checked this key very carefully.\n"));
853                 break;
854               }
855           }
856
857         tty_printf("\n");
858
859         if( opt.batch && opt.answer_yes )
860           ;
861         else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
862             continue;
863
864         /* now we can sign the user ids */
865       reloop: /* (must use this, because we are modifing the list) */
866         primary_pk = NULL;
867         for( node=keyblock; node; node = node->next ) {
868             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
869                 primary_pk = node->pkt->pkt.public_key;
870             else if( node->pkt->pkttype == PKT_USER_ID
871                      && (node->flag & NODFLG_MARK_A) ) {
872                 PACKET *pkt;
873                 PKT_signature *sig;
874                 struct sign_attrib attrib;
875
876                 assert( primary_pk );
877                 memset( &attrib, 0, sizeof attrib );
878                 attrib.non_exportable = local;
879                 attrib.non_revocable = nonrevocable;
880                 attrib.trust_depth = trust_depth;
881                 attrib.trust_value = trust_value;
882                 attrib.trust_regexp = trust_regexp;
883                 node->flag &= ~NODFLG_MARK_A;
884
885                 /* we force creation of a v4 signature for local
886                  * signatures, otherwise we would not generate the
887                  * subpacket with v3 keys and the signature becomes
888                  * exportable */
889
890                 if(selfsig)
891                   rc = make_keysig_packet( &sig, primary_pk,
892                                            node->pkt->pkt.user_id,
893                                            NULL,
894                                            sk,
895                                            0x13, 0, force_v4?4:0, 0, 0,
896                                            keygen_add_std_prefs, primary_pk);
897                 else
898                   rc = make_keysig_packet( &sig, primary_pk,
899                                            node->pkt->pkt.user_id,
900                                            NULL,
901                                            sk,
902                                            class, 0, force_v4?4:0,
903                                            timestamp, duration,
904                                            sign_mk_attrib, &attrib );
905                 if( rc ) {
906                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
907                     goto leave;
908                 }
909
910                 *ret_modified = 1; /* we changed the keyblock */
911                 update_trust = 1;
912
913                 pkt = m_alloc_clear( sizeof *pkt );
914                 pkt->pkttype = PKT_SIGNATURE;
915                 pkt->pkt.signature = sig;
916                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
917                 goto reloop;
918             }
919         }
920
921         /* Delete any sigs that got promoted */
922         for( node=keyblock; node; node = node->next )
923           if( node->flag & NODFLG_DELSIG)
924             delete_kbnode(node);
925     } /* end loop over signators */
926
927   leave:
928     release_sk_list( sk_list );
929     if( sk )
930         free_secret_key(sk);
931     return rc;
932 }
933
934
935
936 /****************
937  * Change the passphrase of the primary and all secondary keys.
938  * We use only one passphrase for all keys.
939  */
940 static int
941 change_passphrase( KBNODE keyblock )
942 {
943     int rc = 0;
944     int changed=0;
945     KBNODE node;
946     PKT_secret_key *sk;
947     char *passphrase = NULL;
948     int no_primary_secrets = 0;
949
950     node = find_kbnode( keyblock, PKT_SECRET_KEY );
951     if( !node ) {
952         log_error("Oops; secret key not found anymore!\n");
953         goto leave;
954     }
955     sk = node->pkt->pkt.secret_key;
956
957     switch( is_secret_key_protected( sk ) ) {
958       case -1:
959         rc = G10ERR_PUBKEY_ALGO;
960         break;
961       case 0:
962         tty_printf(_("This key is not protected.\n"));
963         break;
964       default:
965         if( sk->protect.s2k.mode == 1001 ) {
966             tty_printf(_("Secret parts of primary key are not available.\n"));
967             no_primary_secrets = 1;
968         }
969         else {
970             tty_printf(_("Key is protected.\n"));
971             rc = check_secret_key( sk, 0 );
972             if( !rc )
973                 passphrase = get_last_passphrase();
974         }
975         break;
976     }
977
978     /* unprotect all subkeys (use the supplied passphrase or ask)*/
979     for(node=keyblock; !rc && node; node = node->next ) {
980         if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
981             PKT_secret_key *subsk = node->pkt->pkt.secret_key;
982             set_next_passphrase( passphrase );
983             rc = check_secret_key( subsk, 0 );
984             if( !rc && !passphrase )
985                 passphrase = get_last_passphrase();
986         }
987     }
988
989     if( rc )
990         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
991     else {
992         DEK *dek = NULL;
993         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
994         const char *errtext = NULL;
995
996         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
997
998         set_next_passphrase( NULL );
999         for(;;) {
1000             s2k->mode = opt.s2k_mode;
1001             s2k->hash_algo = opt.s2k_digest_algo;
1002             dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
1003                                      s2k, 2, errtext, NULL);
1004             if( !dek ) {
1005                 errtext = N_("passphrase not correctly repeated; try again");
1006                 tty_printf ("%s.\n", _(errtext));
1007             }
1008             else if( !dek->keylen ) {
1009                 rc = 0;
1010                 tty_printf(_( "You don't want a passphrase -"
1011                             " this is probably a *bad* idea!\n\n"));
1012                 if( cpr_get_answer_is_yes("change_passwd.empty.okay",
1013                                _("Do you really want to do this? ")))
1014                   {
1015                     changed++;
1016                     break;
1017                   }
1018             }
1019             else { /* okay */
1020                 rc = 0;
1021                 if( !no_primary_secrets ) {
1022                     sk->protect.algo = dek->algo;
1023                     sk->protect.s2k = *s2k;
1024                     rc = protect_secret_key( sk, dek );
1025                 }
1026                 for(node=keyblock; !rc && node; node = node->next ) {
1027                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1028                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
1029                         subsk->protect.algo = dek->algo;
1030                         subsk->protect.s2k = *s2k;
1031                         rc = protect_secret_key( subsk, dek );
1032                     }
1033                 }
1034                 if( rc )
1035                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
1036                 else
1037                     changed++;
1038                 break;
1039             }
1040         }
1041         m_free(s2k);
1042         m_free(dek);
1043     }
1044
1045   leave:
1046     m_free( passphrase );
1047     set_next_passphrase( NULL );
1048     return changed && !rc;
1049 }
1050
1051
1052 /****************
1053  * There are some keys out (due to a bug in gnupg), where the sequence
1054  * of the packets is wrong.  This function fixes that.
1055  * Returns: true if the keyblock has been fixed.
1056  *
1057  * Note:  This function does not work if there is more than one user ID.
1058  */
1059 static int
1060 fix_keyblock( KBNODE keyblock )
1061 {
1062     KBNODE node, last, subkey;
1063     int fixed=0;
1064
1065     /* locate key signatures of class 0x10..0x13 behind sub key packets */
1066     for( subkey=last=NULL, node = keyblock; node;
1067                                             last=node, node = node->next ) {
1068         switch( node->pkt->pkttype ) {
1069           case PKT_PUBLIC_SUBKEY:
1070           case PKT_SECRET_SUBKEY:
1071             if( !subkey )
1072                 subkey = last; /* actually it is the one before the subkey */
1073             break;
1074           case PKT_SIGNATURE:
1075             if( subkey ) {
1076                 PKT_signature *sig = node->pkt->pkt.signature;
1077                 if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
1078                     log_info(_(
1079                         "moving a key signature to the correct place\n"));
1080                     last->next = node->next;
1081                     node->next = subkey->next;
1082                     subkey->next = node;
1083                     node = last;
1084                     fixed=1;
1085                 }
1086             }
1087             break;
1088           default: break;
1089         }
1090     }
1091
1092     return fixed;
1093 }
1094
1095 /****************
1096  * Menu driven key editor.  If seckey_check is true, then a secret key
1097  * that matches username will be looked for.  If it is false, not all
1098  * commands will be available.
1099  *
1100  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
1101  */
1102
1103 void
1104 keyedit_menu( const char *username, STRLIST locusr,
1105               STRLIST commands, int quiet, int seckey_check )
1106 {
1107     enum cmdids { cmdNONE = 0,
1108            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
1109            cmdTSIGN, cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY,
1110            cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID,
1111            cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER,
1112            cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
1113            cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF,
1114            cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
1115            cmdNOP };
1116     static struct { const char *name;
1117                     enum cmdids id;
1118                     int need_sk;
1119                     int not_with_sk;
1120                     const char *desc;
1121                   } cmds[] = {
1122         { N_("quit")    , cmdQUIT      , 0,0, N_("quit this menu") },
1123         { N_("q")       , cmdQUIT      , 0,0, NULL   },
1124         { N_("save")    , cmdSAVE      , 0,0, N_("save and quit") },
1125         { N_("help")    , cmdHELP      , 0,0, N_("show this help") },
1126         {    "?"        , cmdHELP      , 0,0, NULL   },
1127         { N_("fpr")     , cmdFPR       , 0,0, N_("show fingerprint") },
1128         { N_("list")    , cmdLIST      , 0,0, N_("list key and user IDs") },
1129         { N_("l")       , cmdLIST      , 0,0, NULL   },
1130         { N_("uid")     , cmdSELUID    , 0,0, N_("select user ID N") },
1131         { N_("key")     , cmdSELKEY    , 0,0, N_("select secondary key N") },
1132         { N_("check")   , cmdCHECK     , 0,0, N_("list signatures") },
1133         { N_("c")       , cmdCHECK     , 0,0, NULL },
1134         { N_("sign")    , cmdSIGN      , 0,1, N_("sign the key") },
1135         { N_("s")       , cmdSIGN      , 0,1, NULL },
1136         { N_("tsign")   , cmdTSIGN     , 0,1, N_("make a trust signature")},
1137         { N_("lsign")   , cmdLSIGN     , 0,1, N_("sign the key locally") },
1138         { N_("nrsign")  , cmdNRSIGN    , 0,1, N_("sign the key non-revocably") },
1139         { N_("nrlsign") , cmdNRLSIGN   , 0,1, N_("sign the key locally and non-revocably") },
1140         { N_("debug")   , cmdDEBUG     , 0,0, NULL },
1141         { N_("adduid")  , cmdADDUID    , 1,1, N_("add a user ID") },
1142         { N_("addphoto"), cmdADDPHOTO  , 1,1, N_("add a photo ID") },
1143         { N_("deluid")  , cmdDELUID    , 0,1, N_("delete user ID") },
1144         /* delphoto is really deluid in disguise */
1145         { N_("delphoto"), cmdDELUID    , 0,1, NULL },
1146         { N_("addkey")  , cmdADDKEY    , 1,1, N_("add a secondary key") },
1147         { N_("delkey")  , cmdDELKEY    , 0,1, N_("delete a secondary key") },
1148         { N_("addrevoker"),cmdADDREVOKER,1,1, N_("add a revocation key") },
1149         { N_("delsig")  , cmdDELSIG    , 0,1, N_("delete signatures") },
1150         { N_("expire")  , cmdEXPIRE    , 1,1, N_("change the expire date") },
1151         { N_("primary") , cmdPRIMARY   , 1,1, N_("flag user ID as primary")},
1152         { N_("toggle")  , cmdTOGGLE    , 1,0, N_("toggle between secret "
1153                                                  "and public key listing") },
1154         { N_("t"     )  , cmdTOGGLE    , 1,0, NULL },
1155         { N_("pref")    , cmdPREF      , 0,1, N_("list preferences (expert)")},
1156         { N_("showpref"), cmdSHOWPREF  , 0,1, N_("list preferences (verbose)") },
1157         { N_("setpref") , cmdSETPREF   , 1,1, N_("set preference list") },
1158         { N_("updpref") , cmdUPDPREF   , 1,1, N_("updated preferences") },
1159         { N_("keyserver"),cmdPREFKS    , 1,1, N_("set preferred keyserver URL")},
1160         { N_("passwd")  , cmdPASSWD    , 1,1, N_("change the passphrase") },
1161         { N_("trust")   , cmdTRUST     , 0,1, N_("change the ownertrust") },
1162         { N_("revsig")  , cmdREVSIG    , 0,1, N_("revoke signatures") },
1163         { N_("revuid")  , cmdREVUID    , 1,1, N_("revoke a user ID") },
1164         { N_("revkey")  , cmdREVKEY    , 1,1, N_("revoke a secondary key") },
1165         { N_("disable") , cmdDISABLEKEY, 0,1, N_("disable a key") },
1166         { N_("enable")  , cmdENABLEKEY , 0,1, N_("enable a key") },
1167         { N_("showphoto"),cmdSHOWPHOTO , 0,0, N_("show photo ID") },
1168
1169     { NULL, cmdNONE } };
1170     enum cmdids cmd = 0;
1171     int rc = 0;
1172     KBNODE keyblock = NULL;
1173     KEYDB_HANDLE kdbhd = NULL;
1174     KBNODE sec_keyblock = NULL;
1175     KEYDB_HANDLE sec_kdbhd = NULL;
1176     KBNODE cur_keyblock;
1177     char *answer = NULL;
1178     int redisplay = 1;
1179     int modified = 0;
1180     int sec_modified = 0;
1181     int toggle;
1182     int have_commands = !!commands;
1183
1184     if ( opt.command_fd != -1 )
1185         ;
1186     else if( opt.batch && !have_commands  ) {
1187         log_error(_("can't do that in batchmode\n"));
1188         goto leave;
1189     }
1190
1191     /* get the public key */
1192     rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1);
1193     if( rc )
1194         goto leave;
1195     if( fix_keyblock( keyblock ) )
1196         modified++;
1197     if( collapse_uids( &keyblock ) )
1198         modified++;
1199     reorder_keyblock(keyblock);
1200
1201     if(seckey_check)
1202       {/* see whether we have a matching secret key */
1203         PKT_public_key *pk = keyblock->pkt->pkt.public_key;
1204
1205         sec_kdbhd = keydb_new (1);
1206         {
1207             byte afp[MAX_FINGERPRINT_LEN];
1208             size_t an;
1209
1210             fingerprint_from_pk (pk, afp, &an);
1211             while (an < MAX_FINGERPRINT_LEN) 
1212                 afp[an++] = 0;
1213             rc = keydb_search_fpr (sec_kdbhd, afp);
1214         }
1215         if (!rc) {
1216             rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock);
1217             if (rc) {
1218                 log_error (_("error reading secret keyblock `%s': %s\n"),
1219                                                 username, g10_errstr(rc));
1220             }
1221             else {
1222                 merge_keys_and_selfsig( sec_keyblock );
1223                 if( fix_keyblock( sec_keyblock ) )
1224                     sec_modified++;
1225             }
1226         }
1227
1228         if (rc) {
1229             sec_keyblock = NULL;
1230             keydb_release (sec_kdbhd); sec_kdbhd = NULL;
1231             rc = 0;
1232         }
1233
1234         if( sec_keyblock && !quiet )
1235           tty_printf(_("Secret key is available.\n"));
1236     }
1237
1238     toggle = 0;
1239     cur_keyblock = keyblock;
1240     for(;;) { /* main loop */
1241         int i, arg_number, photo;
1242         const char *arg_string = "";
1243         char *p;
1244         PKT_public_key *pk=keyblock->pkt->pkt.public_key;
1245
1246         tty_printf("\n");
1247         if( redisplay && !quiet )
1248           {
1249             show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
1250             tty_printf("\n");
1251             redisplay = 0;
1252           }
1253         do {
1254             m_free(answer);
1255             if( have_commands ) {
1256                 if( commands ) {
1257                     answer = m_strdup( commands->d );
1258                     commands = commands->next;
1259                 }
1260                 else if( opt.batch ) {
1261                     answer = m_strdup("quit");
1262                 }
1263                 else
1264                     have_commands = 0;
1265             }
1266             if( !have_commands ) {
1267                 answer = cpr_get_no_help("keyedit.prompt", _("Command> "));
1268                 cpr_kill_prompt();
1269             }
1270             trim_spaces(answer);
1271         } while( *answer == '#' );
1272
1273         arg_number = 0; /* Yes, here is the init which egcc complains about */
1274         photo = 0; /* This too */
1275         if( !*answer )
1276             cmd = cmdLIST;
1277         else if( *answer == CONTROL_D )
1278             cmd = cmdQUIT;
1279         else if( digitp(answer ) ) {
1280             cmd = cmdSELUID;
1281             arg_number = atoi(answer);
1282         }
1283         else {
1284             if( (p=strchr(answer,' ')) ) {
1285                 *p++ = 0;
1286                 trim_spaces(answer);
1287                 trim_spaces(p);
1288                 arg_number = atoi(p);
1289                 arg_string = p;
1290             }
1291
1292             for(i=0; cmds[i].name; i++ ) {
1293                 if( !ascii_strcasecmp( answer, cmds[i].name ) )
1294                     break;
1295             }
1296             if( cmds[i].need_sk && !sec_keyblock ) {
1297                 tty_printf(_("Need the secret key to do this.\n"));
1298                 cmd = cmdNOP;
1299             }
1300             else if( cmds[i].not_with_sk && sec_keyblock && toggle ) {
1301                 tty_printf(_("Please use the command \"toggle\" first.\n"));
1302                 cmd = cmdNOP;
1303             }
1304             else
1305                 cmd = cmds[i].id;
1306         }
1307         switch( cmd )  {
1308           case cmdHELP:
1309             for(i=0; cmds[i].name; i++ ) {
1310               if( cmds[i].need_sk && !sec_keyblock )
1311                 ; /* skip if we do not have the secret key */
1312               else if( cmds[i].desc )
1313                 tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
1314             }
1315             break;
1316
1317           case cmdLIST:
1318             redisplay = 1;
1319             break;
1320
1321           case cmdFPR:
1322             show_key_and_fingerprint( keyblock );
1323             break;
1324
1325           case cmdSELUID:
1326             if( menu_select_uid( cur_keyblock, arg_number ) )
1327                 redisplay = 1;
1328             break;
1329
1330           case cmdSELKEY:
1331             if( menu_select_key( cur_keyblock, arg_number ) )
1332                 redisplay = 1;
1333             break;
1334
1335           case cmdCHECK:
1336             /* we can only do this with the public key becuase the
1337              * check functions can't cope with secret keys and it
1338              * is questionable whether this would make sense at all */
1339             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
1340             break;
1341
1342           case cmdSIGN: /* sign (only the public key) */
1343           case cmdLSIGN: /* sign (only the public key) */
1344           case cmdNRSIGN: /* sign (only the public key) */
1345           case cmdNRLSIGN: /* sign (only the public key) */
1346           case cmdTSIGN:
1347             if( pk->is_revoked )
1348               {
1349                 tty_printf(_("Key is revoked."));
1350
1351                 if(opt.expert)
1352                   {
1353                     tty_printf("  ");
1354                     if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay",
1355                                               _("Are you sure you still want "
1356                                                 "to sign it? (y/N) ")))
1357                       break;
1358                   }
1359                 else
1360                   {
1361                     tty_printf(_("  Unable to sign.\n"));
1362                     break;
1363                   }
1364               }
1365
1366             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
1367                 if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
1368                                            _("Really sign all user IDs? ")) ) {
1369                     tty_printf(_("Hint: Select the user IDs to sign\n"));
1370                     break;
1371                 }
1372             }
1373
1374             sign_uids( keyblock, locusr, &modified,
1375                        (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN),
1376                        (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN),
1377                        (cmd == cmdTSIGN));
1378             break;
1379
1380           case cmdDEBUG:
1381             dump_kbnode( cur_keyblock );
1382             break;
1383
1384           case cmdTOGGLE:
1385             toggle = !toggle;
1386             cur_keyblock = toggle? sec_keyblock : keyblock;
1387             redisplay = 1;
1388             break;
1389
1390           case cmdADDPHOTO:
1391             if (RFC2440 || RFC1991 || PGP2)
1392               {
1393                 tty_printf(
1394                    _("This command is not allowed while in %s mode.\n"),
1395                    RFC2440?"OpenPGP":PGP2?"PGP2":"RFC-1991");
1396                 break;
1397               }
1398             photo=1;
1399             /* fall through */
1400
1401           case cmdADDUID:
1402             if( menu_adduid( keyblock, sec_keyblock, photo ) ) {
1403                 redisplay = 1;
1404                 sec_modified = modified = 1;
1405                 merge_keys_and_selfsig( sec_keyblock );
1406                 merge_keys_and_selfsig( keyblock );
1407             }
1408             break;
1409
1410           case cmdDELUID: {
1411                 int n1;
1412
1413                 if( !(n1=count_selected_uids(keyblock)) )
1414                     tty_printf(_("You must select at least one user ID.\n"));
1415                 else if( real_uids_left(keyblock) < 1 )
1416                     tty_printf(_("You can't delete the last user ID!\n"));
1417                 else if( cpr_get_answer_is_yes(
1418                             "keyedit.remove.uid.okay",
1419                         n1 > 1? _("Really remove all selected user IDs? ")
1420                               : _("Really remove this user ID? ")
1421                        ) ) {
1422                     menu_deluid( keyblock, sec_keyblock );
1423                     redisplay = 1;
1424                     modified = 1;
1425                     if( sec_keyblock )
1426                        sec_modified = 1;
1427                 }
1428             }
1429             break;
1430
1431           case cmdDELSIG: {
1432                 int n1;
1433
1434                 if( !(n1=count_selected_uids(keyblock)) )
1435                     tty_printf(_("You must select at least one user ID.\n"));
1436                 else if( menu_delsig( keyblock ) ) {
1437                     /* no redisplay here, because it may scroll away some
1438                      * status output of delsig */
1439                     modified = 1;
1440                 }
1441             }
1442             break;
1443
1444           case cmdADDKEY:
1445             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
1446                 redisplay = 1;
1447                 sec_modified = modified = 1;
1448                 merge_keys_and_selfsig( sec_keyblock );
1449                 merge_keys_and_selfsig( keyblock );
1450             }
1451             break;
1452
1453
1454           case cmdDELKEY: {
1455                 int n1;
1456
1457                 if( !(n1=count_selected_keys( keyblock )) )
1458                     tty_printf(_("You must select at least one key.\n"));
1459                 else if( !cpr_get_answer_is_yes( "keyedit.remove.subkey.okay",
1460                        n1 > 1?
1461                         _("Do you really want to delete the selected keys? "):
1462                         _("Do you really want to delete this key? ")
1463                        ))
1464                     ;
1465                 else {
1466                     menu_delkey( keyblock, sec_keyblock );
1467                     redisplay = 1;
1468                     modified = 1;
1469                     if( sec_keyblock )
1470                        sec_modified = 1;
1471                 }
1472             }
1473             break;
1474
1475           case cmdADDREVOKER:
1476             {
1477               int sensitive=0;
1478
1479               if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0)
1480                 sensitive=1;
1481               if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
1482                 redisplay = 1;
1483                 sec_modified = modified = 1;
1484                 merge_keys_and_selfsig( sec_keyblock );
1485                 merge_keys_and_selfsig( keyblock );
1486               }
1487             }
1488             break;
1489
1490           case cmdREVUID: {
1491                 int n1;
1492
1493                 if( !(n1=count_selected_uids(keyblock)) )
1494                     tty_printf(_("You must select at least one user ID.\n"));
1495                 else if( cpr_get_answer_is_yes(
1496                             "keyedit.revoke.uid.okay",
1497                         n1 > 1? _("Really revoke all selected user IDs? ")
1498                               : _("Really revoke this user ID? ")
1499                        ) ) {
1500                   if(menu_revuid(keyblock,sec_keyblock))
1501                     {
1502                       modified=1;
1503                       redisplay=1;
1504                     }
1505                 }
1506             }
1507             break;
1508
1509           case cmdREVKEY: {
1510                 int n1;
1511
1512                 if( !(n1=count_selected_keys( keyblock )) )
1513                     tty_printf(_("You must select at least one key.\n"));
1514                 else if( sec_keyblock && !cpr_get_answer_is_yes(
1515                             "keyedit.revoke.subkey.okay",
1516                        n1 > 1?
1517                         _("Do you really want to revoke the selected keys? "):
1518                         _("Do you really want to revoke this key? ")
1519                        ))
1520                     ;
1521                 else {
1522                     if( menu_revkey( keyblock, sec_keyblock ) ) {
1523                         modified = 1;
1524                         /*sec_modified = 1;*/
1525                     }
1526                     redisplay = 1;
1527                 }
1528             }
1529             break;
1530
1531           case cmdEXPIRE:
1532             if( menu_expire( keyblock, sec_keyblock ) ) {
1533                 merge_keys_and_selfsig( sec_keyblock );
1534                 merge_keys_and_selfsig( keyblock );
1535                 sec_modified = 1;
1536                 modified = 1;
1537                 redisplay = 1;
1538             }
1539             break;
1540
1541           case cmdPRIMARY:
1542             if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
1543                 merge_keys_and_selfsig( keyblock );
1544                 modified = 1;
1545                 redisplay = 1;
1546             }
1547             break;
1548
1549           case cmdPASSWD:
1550             if( change_passphrase( sec_keyblock ) )
1551                 sec_modified = 1;
1552             break;
1553
1554           case cmdTRUST:
1555             if(opt.trust_model==TM_EXTERNAL)
1556               {
1557                 tty_printf(_("Owner trust may not be set while "
1558                              "using an user provided trust database\n"));
1559                 break;
1560               }
1561
1562             show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 );
1563             tty_printf("\n");
1564             if( edit_ownertrust( find_kbnode( keyblock,
1565                                  PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) ) {
1566                 redisplay = 1;
1567                 /* No real need to set update_trust here as
1568                    edit_ownertrust() calls revalidation_mark()
1569                    anyway. */
1570                 update_trust=1;
1571             }
1572             break;
1573
1574           case cmdPREF:
1575             show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 );
1576             break;
1577
1578           case cmdSHOWPREF:
1579             show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 );
1580             break;
1581
1582           case cmdSETPREF:
1583             keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0);
1584             break;
1585
1586           case cmdUPDPREF: 
1587             {
1588               PKT_user_id *temp=keygen_get_std_prefs();
1589               tty_printf(_("Set preference list to:\n"));
1590               show_prefs(temp,1);
1591               m_free(temp);
1592             }
1593             if (cpr_get_answer_is_yes ("keyedit.updpref.okay",
1594                                         count_selected_uids (keyblock)?
1595                                         _("Really update the preferences"
1596                                           " for the selected user IDs? "):
1597                                        _("Really update the preferences? "))){
1598
1599                 if ( menu_set_preferences (keyblock, sec_keyblock) ) {
1600                     merge_keys_and_selfsig (keyblock);
1601                     modified = 1;
1602                     redisplay = 1;
1603                 }
1604             }
1605             break;
1606
1607           case cmdPREFKS:
1608             if( menu_set_keyserver_url ( keyblock, sec_keyblock ) ) {
1609                 merge_keys_and_selfsig( keyblock );
1610                 modified = 1;
1611                 redisplay = 1;
1612             }
1613             break;
1614
1615           case cmdNOP:
1616             break;
1617
1618           case cmdREVSIG:
1619             if( menu_revsig( keyblock ) ) {
1620                 redisplay = 1;
1621                 modified = 1;
1622             }
1623             break;
1624
1625           case cmdENABLEKEY:
1626           case cmdDISABLEKEY:
1627             if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) {
1628                 redisplay = 1;
1629                 modified = 1;
1630             }
1631             break;
1632
1633          case cmdSHOWPHOTO:
1634            menu_showphoto(keyblock);
1635            break;
1636
1637           case cmdQUIT:
1638             if( have_commands )
1639                 goto leave;
1640             if( !modified && !sec_modified )
1641                 goto leave;
1642             if( !cpr_get_answer_is_yes("keyedit.save.okay",
1643                                         _("Save changes? ")) ) {
1644                 if( cpr_enabled()
1645                     || cpr_get_answer_is_yes("keyedit.cancel.okay",
1646                                              _("Quit without saving? ")) )
1647                     goto leave;
1648                 break;
1649             }
1650             /* fall thru */
1651           case cmdSAVE:
1652             if( modified || sec_modified  ) {
1653                 if( modified ) {
1654                     rc = keydb_update_keyblock (kdbhd, keyblock);
1655                     if( rc ) {
1656                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
1657                         break;
1658                     }
1659                 }
1660                 if( sec_modified ) {
1661                     rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock );
1662                     if( rc ) {
1663                         log_error( _("update secret failed: %s\n"),
1664                                    g10_errstr(rc) );
1665                         break;
1666                     }
1667                 }
1668             }
1669             else
1670                 tty_printf(_("Key not changed so no update needed.\n"));
1671
1672             if( update_trust )
1673               {
1674                 revalidation_mark ();
1675                 update_trust=0;
1676               }
1677             goto leave;
1678
1679           case cmdINVCMD:
1680           default:
1681             tty_printf("\n");
1682             tty_printf(_("Invalid command  (try \"help\")\n"));
1683             break;
1684         }
1685     } /* end main loop */
1686
1687   leave:
1688     release_kbnode( keyblock );
1689     release_kbnode( sec_keyblock );
1690     keydb_release (kdbhd);
1691     m_free(answer);
1692 }
1693
1694
1695 /****************
1696  * show preferences of a public keyblock.
1697  */
1698 static void
1699 show_prefs (PKT_user_id *uid, int verbose)
1700 {
1701     const prefitem_t fake={0,0};
1702     const prefitem_t *prefs;
1703     int i;
1704
1705     if( !uid )
1706         return;
1707
1708     if( uid->prefs )
1709         prefs=uid->prefs;
1710     else if(verbose)
1711         prefs=&fake;
1712     else
1713       return;
1714
1715     if (verbose) {
1716         int any, des_seen=0, sha1_seen=0, uncomp_seen=0;
1717         tty_printf ("     ");
1718         tty_printf (_("Cipher: "));
1719         for(i=any=0; prefs[i].type; i++ ) {
1720             if( prefs[i].type == PREFTYPE_SYM ) {
1721                 const char *s = cipher_algo_to_string (prefs[i].value);
1722                 
1723                 if (any)
1724                     tty_printf (", ");
1725                 any = 1;
1726                 /* We don't want to display strings for experimental algos */
1727                 if (s && prefs[i].value < 100 )
1728                     tty_printf ("%s", s );
1729                 else
1730                     tty_printf ("[%d]", prefs[i].value);
1731                 if (prefs[i].value == CIPHER_ALGO_3DES )
1732                     des_seen = 1;
1733             }    
1734         }
1735         if (!des_seen) {
1736             if (any)
1737                 tty_printf (", ");
1738             tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES));
1739         }
1740         tty_printf ("\n     ");
1741         tty_printf (_("Digest: "));
1742         for(i=any=0; prefs[i].type; i++ ) {
1743             if( prefs[i].type == PREFTYPE_HASH ) {
1744                 const char *s = digest_algo_to_string (prefs[i].value);
1745                 
1746                 if (any)
1747                     tty_printf (", ");
1748                 any = 1;
1749                 /* We don't want to display strings for experimental algos */
1750                 if (s && prefs[i].value < 100 )
1751                     tty_printf ("%s", s );
1752                 else
1753                     tty_printf ("[%d]", prefs[i].value);
1754                 if (prefs[i].value == DIGEST_ALGO_SHA1 )
1755                     sha1_seen = 1;
1756             }
1757         }
1758         if (!sha1_seen) {
1759             if (any)
1760                 tty_printf (", ");
1761             tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1));
1762         }
1763         tty_printf ("\n     ");
1764         tty_printf (_("Compression: "));
1765         for(i=any=0; prefs[i].type; i++ ) {
1766             if( prefs[i].type == PREFTYPE_ZIP ) {
1767                 const char *s=compress_algo_to_string(prefs[i].value);
1768                 
1769                 if (any)
1770                     tty_printf (", ");
1771                 any = 1;
1772                 /* We don't want to display strings for experimental algos */
1773                 if (s && prefs[i].value < 100 )
1774                     tty_printf ("%s", s );
1775                 else
1776                     tty_printf ("[%d]", prefs[i].value);
1777                 if (prefs[i].value == COMPRESS_ALGO_NONE )
1778                     uncomp_seen = 1;
1779             }
1780         }
1781         if (!uncomp_seen) {
1782             if (any)
1783                 tty_printf (", ");
1784             else {
1785               tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_ZIP));
1786               tty_printf (", ");
1787             }
1788             tty_printf ("%s",compress_algo_to_string(COMPRESS_ALGO_NONE));
1789         }
1790         if(uid->mdc_feature || !uid->ks_modify)
1791           {
1792             tty_printf ("\n     ");
1793             tty_printf (_("Features: "));
1794             any=0;
1795             if(uid->mdc_feature)
1796               {
1797                 tty_printf ("MDC");
1798                 any=1;
1799               }
1800             if(!uid->ks_modify)
1801               {
1802                 if(any)
1803                   tty_printf (", ");
1804                 tty_printf (_("Keyserver no-modify"));
1805               }
1806           }
1807         tty_printf("\n");
1808     }
1809     else {
1810         tty_printf("    ");
1811         for(i=0; prefs[i].type; i++ ) {
1812             tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM   ? 'S' :
1813                                  prefs[i].type == PREFTYPE_HASH  ? 'H' :
1814                                  prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
1815                                  prefs[i].value);
1816         }
1817         if (uid->mdc_feature)
1818             tty_printf (" [mdc]");
1819         if (!uid->ks_modify)
1820             tty_printf (" [no-ks-modify]");
1821         tty_printf("\n");
1822     }
1823 }
1824
1825
1826 /* This is the version of show_key_with_all_names used when
1827    opt.with_colons is used.  It prints all available data in a easy to
1828    parse format and does not translate utf8 */
1829 static void
1830 show_key_with_all_names_colon (KBNODE keyblock)
1831 {
1832   KBNODE node;
1833   int i, j, ulti_hack=0;
1834   byte pk_version=0;
1835   PKT_public_key *primary=NULL;
1836
1837   /* the keys */
1838   for ( node = keyblock; node; node = node->next )
1839     {
1840       if (node->pkt->pkttype == PKT_PUBLIC_KEY
1841           || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) )
1842         {
1843           PKT_public_key *pk = node->pkt->pkt.public_key;
1844           u32 keyid[2];
1845
1846           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1847             {
1848               pk_version = pk->version;
1849               primary=pk;
1850             }
1851
1852           keyid_from_pk (pk, keyid);
1853
1854           fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout);
1855           if (!pk->is_valid)
1856             putchar ('i');
1857           else if (pk->is_revoked)
1858             putchar ('r');
1859           else if (pk->has_expired)
1860             putchar ('e');
1861           else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks ))
1862             {
1863               int trust = get_validity_info (pk, NULL);
1864               if(trust=='u')
1865                 ulti_hack=1;
1866               putchar (trust);
1867             }
1868
1869           printf (":%u:%d:%08lX%08lX:%lu:%lu::",
1870                   nbits_from_pk (pk),
1871                   pk->pubkey_algo,
1872                   (ulong)keyid[0], (ulong)keyid[1],
1873                   (ulong)pk->timestamp,
1874                   (ulong)pk->expiredate );
1875           if (node->pkt->pkttype==PKT_PUBLIC_KEY
1876               && !(opt.fast_list_mode || opt.no_expensive_trust_checks ))
1877             putchar(get_ownertrust_info (pk));
1878           putchar(':');
1879           putchar('\n');
1880           
1881           print_fingerprint (pk, NULL, 0);
1882
1883           /* print the revoker record */
1884           if( !pk->revkey && pk->numrevkeys )
1885             BUG();
1886           else
1887             {
1888               for (i=0; i < pk->numrevkeys; i++)
1889                 {
1890                   byte *p;
1891
1892                   printf ("rvk:::%d::::::", pk->revkey[i].algid);
1893                   p = pk->revkey[i].fpr;
1894                   for (j=0; j < 20; j++, p++ )
1895                     printf ("%02X", *p);
1896                   printf (":%02x%s:\n", pk->revkey[i].class,
1897                           (pk->revkey[i].class&0x40)?"s":"");
1898                 }
1899             }
1900         }
1901     }
1902   
1903     /* the user ids */
1904     i = 0;
1905     for (node = keyblock; node; node = node->next) 
1906       {
1907         if ( node->pkt->pkttype == PKT_USER_ID )
1908           {
1909             PKT_user_id *uid = node->pkt->pkt.user_id;
1910
1911             ++i;
1912
1913             if(uid->attrib_data)
1914               printf("uat:");
1915             else
1916               printf("uid:");
1917
1918             if ( uid->is_revoked )
1919               printf("r::::::::");
1920             else if ( uid->is_expired )
1921               printf("e::::::::");
1922             else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1923               printf("::::::::");
1924             else
1925               {
1926                 int uid_validity;
1927
1928                 if( primary && !ulti_hack )
1929                   uid_validity = get_validity_info( primary, uid );
1930                 else
1931                   uid_validity = 'u';
1932                 printf("%c::::::::",uid_validity);
1933               }
1934
1935             if(uid->attrib_data)
1936               printf ("%u %lu",uid->numattribs,uid->attrib_len);
1937             else
1938               print_string (stdout, uid->name, uid->len, ':');
1939
1940             putchar (':');
1941             /* signature class */
1942             putchar (':');
1943             /* capabilities */
1944             putchar (':');
1945             /* preferences */
1946             if (pk_version>3 || uid->selfsigversion>3)
1947               {
1948                 const prefitem_t *prefs = uid->prefs;
1949                 
1950                 for (j=0; prefs && prefs[j].type; j++)
1951                   {
1952                     if (j)
1953                       putchar (' ');
1954                     printf ("%c%d", prefs[j].type == PREFTYPE_SYM   ? 'S' :
1955                             prefs[j].type == PREFTYPE_HASH  ? 'H' :
1956                             prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
1957                             prefs[j].value);
1958                   } 
1959                 if (uid->mdc_feature)
1960                   printf (",mdc");
1961                 if (!uid->ks_modify)
1962                   printf (",no-ks-modify");
1963               } 
1964             putchar (':');
1965             /* flags */
1966             printf ("%d,", i);
1967             if (uid->is_primary)
1968               putchar ('p');
1969             if (uid->is_revoked)
1970               putchar ('r');
1971             if (uid->is_expired)
1972               putchar ('e');
1973             if ((node->flag & NODFLG_SELUID))
1974               putchar ('s');
1975             if ((node->flag & NODFLG_MARK_A))
1976               putchar ('m');
1977             putchar (':');
1978             putchar('\n');
1979           }
1980       }
1981 }
1982
1983
1984 /****************
1985  * Display the key a the user ids, if only_marked is true, do only
1986  * so for user ids with mark A flag set and dont display the index number
1987  */
1988 static void
1989 show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
1990                          int with_fpr, int with_subkeys, int with_prefs )
1991 {
1992     KBNODE node;
1993     int i, rc;
1994     int do_warn = 0, indent=0;
1995     byte pk_version=0;
1996     PKT_public_key *primary=NULL;
1997
1998     if (opt.with_colons)
1999       {
2000         show_key_with_all_names_colon (keyblock);
2001         return;
2002       }
2003
2004     /* the keys */
2005     for( node = keyblock; node; node = node->next ) {
2006         if( node->pkt->pkttype == PKT_PUBLIC_KEY
2007             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
2008             PKT_public_key *pk = node->pkt->pkt.public_key;
2009             const char *otrust="err",*trust="err";
2010
2011             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2012                 /* do it here, so that debug messages don't clutter the
2013                  * output */
2014                 static int did_warn = 0;
2015
2016                 trust = get_validity_string (pk, NULL);
2017                 otrust = get_ownertrust_string (pk);
2018
2019                 /* Show a warning once */
2020                 if (!did_warn
2021                     && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) {
2022                     did_warn = 1;
2023                     do_warn = 1;
2024                 }
2025
2026                 pk_version=pk->version;
2027                 primary=pk;
2028             }
2029
2030             if(with_revoker) {
2031                 if( !pk->revkey && pk->numrevkeys )
2032                     BUG();
2033                 else
2034                     for(i=0;i<pk->numrevkeys;i++) {
2035                         u32 r_keyid[2];
2036                         char *user;
2037                         const char *algo=
2038                           pubkey_algo_to_string(pk->revkey[i].algid);
2039
2040                         keyid_from_fingerprint(pk->revkey[i].fpr,
2041                                                MAX_FINGERPRINT_LEN,r_keyid);
2042                         
2043                         user=get_user_id_string (r_keyid);
2044                         tty_printf (_("This key may be revoked by %s key "),
2045                                     algo?algo:"?");
2046                         tty_print_utf8_string (user, strlen (user));
2047                         if ((pk->revkey[i].class&0x40))
2048                           tty_printf (_(" (sensitive)"));
2049                         tty_printf ("\n");
2050                         m_free(user);
2051                       }
2052             }
2053
2054             keyid_from_pk(pk,NULL);
2055             tty_printf("%s%c %4u%c/",
2056                        node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
2057                        (node->flag & NODFLG_SELKEY)? '*':' ',
2058                        nbits_from_pk( pk ),
2059                        pubkey_letter( pk->pubkey_algo ));
2060
2061             if(opt.list_options&LIST_SHOW_LONG_KEYIDS)
2062               tty_printf("%08lX",(ulong)pk->keyid[0]);
2063
2064             tty_printf("%08lX  ",(ulong)pk->keyid[1]);
2065             tty_printf(_("created: %s"),datestr_from_pk(pk));
2066             tty_printf("  ");
2067             if(pk->is_revoked)
2068               tty_printf(_("revoked: %s"),revokestr_from_pk(pk));
2069             else if(pk->has_expired)
2070               tty_printf(_("expired: %s"),expirestr_from_pk(pk));
2071             else
2072               tty_printf(_("expires: %s"),expirestr_from_pk(pk));
2073             tty_printf("\n");
2074
2075             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
2076               {
2077                 if(opt.trust_model!=TM_ALWAYS)
2078                   {
2079                     tty_printf("                     ");
2080                     if(opt.list_options&LIST_SHOW_LONG_KEYIDS)
2081                       tty_printf("        ");
2082                     /* Ownertrust is only meaningful for the PGP or
2083                        classic trust models */
2084                     if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
2085                       {
2086                         int width=14-strlen(otrust);
2087                         if(width<=0)
2088                           width=1;
2089                         tty_printf(_("trust: %s"), otrust);
2090                         tty_printf("%*s",width,"");
2091                       }
2092                     
2093                     tty_printf(_("validity: %s"), trust );
2094                     tty_printf("\n");
2095                   }
2096                 if( node->pkt->pkttype == PKT_PUBLIC_KEY
2097                     && (get_ownertrust (pk)&TRUST_FLAG_DISABLED))
2098                   {
2099                     tty_printf("*** ");
2100                     tty_printf(_("This key has been disabled"));
2101                     tty_printf("\n");
2102                   }
2103               }
2104
2105             if( node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr )
2106               {
2107                 print_fingerprint ( pk, NULL, 2 );
2108                 tty_printf("\n");
2109               }
2110         }
2111         else if( node->pkt->pkttype == PKT_SECRET_KEY
2112             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
2113             PKT_secret_key *sk = node->pkt->pkt.secret_key;
2114             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2115                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
2116                           (node->flag & NODFLG_SELKEY)? '*':' ',
2117                           nbits_from_sk( sk ),
2118                           pubkey_letter( sk->pubkey_algo ),
2119                           (ulong)keyid_from_sk(sk,NULL),
2120                           datestr_from_sk(sk),
2121                           expirestr_from_sk(sk) );
2122             tty_printf("\n");
2123         }
2124         else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
2125                  && node->pkt->pkt.signature->sig_class == 0x28       ) {
2126             PKT_signature *sig = node->pkt->pkt.signature;
2127
2128             rc = check_key_signature( keyblock, node, NULL );
2129             if( !rc )
2130                 tty_printf( _("rev! subkey has been revoked: %s\n"),
2131                             datestr_from_sig( sig ) );
2132             else if( rc == G10ERR_BAD_SIGN )
2133                 tty_printf( _("rev- faked revocation found\n") );
2134             else if( rc )
2135                 tty_printf( _("rev? problem checking revocation: %s\n"),
2136                                                          g10_errstr(rc) );
2137         }
2138     }
2139     
2140     /* the user ids */
2141
2142     for( node = keyblock; node; node = node->next )
2143       {
2144         if(node->pkt->pkttype == PKT_USER_ID
2145            && (node->pkt->pkt.user_id->is_revoked
2146                || node->pkt->pkt.user_id->is_expired))
2147           {
2148             indent=1;
2149             break;
2150           }
2151       }
2152
2153     i = 0;
2154     for( node = keyblock; node; node = node->next ) {
2155         if( node->pkt->pkttype == PKT_USER_ID ) {
2156             PKT_user_id *uid = node->pkt->pkt.user_id;
2157             ++i;
2158             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
2159                 if(uid->is_revoked)
2160                   tty_printf("[%8.8s] ",_("revoked"));
2161                 else if(uid->is_expired)
2162                   tty_printf("[%8.8s] ",_("expired"));
2163                 else if(opt.list_options&LIST_SHOW_VALIDITY && primary)
2164                   tty_printf("[%8.8s] ",
2165                              trust_value_to_string(get_validity(primary,uid)));
2166                 else if(indent)
2167                   tty_printf("           ");
2168                 if( only_marked )
2169                    tty_printf("     ");
2170                 else if( node->flag & NODFLG_SELUID )
2171                    tty_printf("(%d)* ", i);
2172                 else if( uid->is_primary )
2173                    tty_printf("(%d). ", i);
2174                 else
2175                    tty_printf("(%d)  ", i);
2176                 tty_print_utf8_string( uid->name, uid->len );
2177                 tty_printf("\n");
2178                 if( with_prefs )
2179                   {
2180                     if(pk_version>3 || uid->selfsigversion>3)
2181                       show_prefs (uid, with_prefs == 2);
2182                     else
2183                       tty_printf(_("There are no preferences on a "
2184                                    "PGP 2.x-style user ID.\n"));
2185                   }
2186             }
2187         }
2188     }
2189
2190     if (do_warn)
2191         tty_printf (_("Please note that the shown key validity "
2192                       "is not necessarily correct\n"
2193                       "unless you restart the program.\n")); 
2194
2195 }
2196
2197
2198 /* Display basic key information.  This fucntion is suitable to show
2199    information on the key without any dependencies on the trustdb or
2200    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
2201    a secret key.*/
2202 void
2203 show_basic_key_info ( KBNODE keyblock )
2204 {
2205   KBNODE node;
2206   int i;
2207
2208   /* The primary key */
2209   for (node = keyblock; node; node = node->next)
2210     {
2211       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
2212         {
2213           PKT_public_key *pk = node->pkt->pkt.public_key;
2214           
2215           /* Note, we use the same format string as in other show
2216              functions to make the translation job easier. */
2217           tty_printf (_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2218                       node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
2219                       ' ',
2220                       nbits_from_pk( pk ),
2221                       pubkey_letter( pk->pubkey_algo ),
2222                       (ulong)keyid_from_pk(pk,NULL),
2223                       datestr_from_pk(pk),
2224                       expirestr_from_pk(pk) );
2225           tty_printf("\n");
2226           print_fingerprint ( pk, NULL, 3 );
2227           tty_printf("\n");
2228         }
2229       else if (node->pkt->pkttype == PKT_SECRET_KEY)
2230         {
2231           PKT_secret_key *sk = node->pkt->pkt.secret_key;
2232           tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2233                      node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
2234                      ' ',
2235                      nbits_from_sk( sk ),
2236                      pubkey_letter( sk->pubkey_algo ),
2237                      (ulong)keyid_from_sk(sk,NULL),
2238                      datestr_from_sk(sk),
2239                      expirestr_from_sk(sk) );
2240           tty_printf("\n");
2241           print_fingerprint (NULL, sk, 3 );
2242           tty_printf("\n");
2243         }
2244     }
2245
2246   /* The user IDs. */
2247   for (i=0, node = keyblock; node; node = node->next)
2248     {
2249       if (node->pkt->pkttype == PKT_USER_ID)
2250         {
2251           PKT_user_id *uid = node->pkt->pkt.user_id;
2252           ++i;
2253      
2254           tty_printf ("     ");
2255           if (uid->is_revoked)
2256             tty_printf (_("[revoked] "));
2257           else if ( uid->is_expired )
2258             tty_printf (_("[expired] "));
2259           tty_print_utf8_string (uid->name, uid->len);
2260           tty_printf ("\n");
2261         }
2262     }
2263 }
2264
2265 static void
2266 show_key_and_fingerprint( KBNODE keyblock )
2267 {
2268     KBNODE node;
2269     PKT_public_key *pk = NULL;
2270
2271     for( node = keyblock; node; node = node->next ) {
2272         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2273             pk = node->pkt->pkt.public_key;
2274             tty_printf("pub   %4u%c/%08lX %s ",
2275                           nbits_from_pk( pk ),
2276                           pubkey_letter( pk->pubkey_algo ),
2277                           (ulong)keyid_from_pk(pk,NULL),
2278                           datestr_from_pk(pk) );
2279         }
2280         else if( node->pkt->pkttype == PKT_USER_ID ) {
2281             PKT_user_id *uid = node->pkt->pkt.user_id;
2282             tty_print_utf8_string( uid->name, uid->len );
2283             break;
2284         }
2285     }
2286     tty_printf("\n");
2287     if( pk )
2288         print_fingerprint( pk, NULL, 2 );
2289 }
2290
2291
2292 /* Show a warning if no uids on the key have the primary uid flag
2293    set. */
2294 static void
2295 no_primary_warning(KBNODE keyblock, int uids)
2296 {
2297   KBNODE node;
2298   int select_all=1,have_uid=0,uid_count=0;
2299
2300   if(uids)
2301     select_all=!count_selected_uids(keyblock);
2302
2303   /* TODO: if we ever start behaving differently with a primary or
2304      non-primary attribute ID, we will need to check for attributes
2305      here as well. */
2306
2307   for(node=keyblock; node; node = node->next)
2308     {
2309       if(node->pkt->pkttype==PKT_USER_ID
2310          && node->pkt->pkt.user_id->attrib_data==NULL)
2311         {
2312           uid_count++;
2313
2314           if((select_all || (node->flag & NODFLG_SELUID))
2315              && node->pkt->pkt.user_id->is_primary==2)
2316             have_uid|=2;
2317           else
2318             have_uid|=1;
2319         }
2320     }
2321
2322   if(uid_count>1 && have_uid&1 && !(have_uid&2))
2323     log_info(_("WARNING: no user ID has been marked as primary.  This command "
2324                "may\n              cause a different user ID to become the assumed primary.\n"));
2325 }
2326
2327 /****************
2328  * Ask for a new user id, do the selfsignature and put it into
2329  * both keyblocks.
2330  * Return true if there is a new user id
2331  */
2332 static int
2333 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
2334 {
2335     PKT_user_id *uid;
2336     PKT_public_key *pk=NULL;
2337     PKT_secret_key *sk=NULL;
2338     PKT_signature *sig=NULL;
2339     PACKET *pkt;
2340     KBNODE node;
2341     KBNODE pub_where=NULL, sec_where=NULL;
2342     int rc;
2343
2344     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
2345         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
2346             pk = node->pkt->pkt.public_key;
2347         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2348             break;
2349     }
2350     if( !node ) /* no subkey */
2351         pub_where = NULL;
2352     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
2353         if( node->pkt->pkttype == PKT_SECRET_KEY )
2354             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2355         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
2356             break;
2357     }
2358     if( !node ) /* no subkey */
2359         sec_where = NULL;
2360     assert(pk && sk);
2361
2362     if(photo) {
2363       int hasattrib=0;
2364
2365       for( node = pub_keyblock; node; node = node->next )
2366         if( node->pkt->pkttype == PKT_USER_ID &&
2367             node->pkt->pkt.user_id->attrib_data!=NULL)
2368           {
2369             hasattrib=1;
2370             break;
2371           }
2372
2373       /* It is legal but bad for compatibility to add a photo ID to a
2374          v3 key as it means that PGP2 will not be able to use that key
2375          anymore.  Also, PGP may not expect a photo on a v3 key.
2376          Don't bother to ask this if the key already has a photo - any
2377          damage has already been done at that point. -dms */
2378       if(pk->version==3 && !hasattrib)
2379         {
2380           if(opt.expert)
2381             {
2382               tty_printf(_("WARNING: This is a PGP2-style key.  "
2383                            "Adding a photo ID may cause some versions\n"
2384                            "         of PGP to reject this key.\n"));
2385
2386               if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay",
2387                                         _("Are you sure you still want "
2388                                           "to add it? (y/N) ")))
2389                 return 0;
2390             }
2391           else
2392             {
2393               tty_printf(_("You may not add a photo ID to "
2394                            "a PGP2-style key.\n"));
2395               return 0;
2396             }
2397         }
2398
2399       uid = generate_photo_id(pk);
2400     } else
2401       uid = generate_user_id();
2402     if( !uid )
2403         return 0;
2404
2405     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
2406                              keygen_add_std_prefs, pk );
2407     free_secret_key( sk );
2408     if( rc ) {
2409         log_error("signing failed: %s\n", g10_errstr(rc) );
2410         free_user_id(uid);
2411         return 0;
2412     }
2413
2414     /* insert/append to secret keyblock */
2415     pkt = m_alloc_clear( sizeof *pkt );
2416     pkt->pkttype = PKT_USER_ID;
2417     pkt->pkt.user_id = scopy_user_id(uid);
2418     node = new_kbnode(pkt);
2419     if( sec_where )
2420         insert_kbnode( sec_where, node, 0 );
2421     else
2422         add_kbnode( sec_keyblock, node );
2423     pkt = m_alloc_clear( sizeof *pkt );
2424     pkt->pkttype = PKT_SIGNATURE;
2425     pkt->pkt.signature = copy_signature(NULL, sig);
2426     if( sec_where )
2427         insert_kbnode( node, new_kbnode(pkt), 0 );
2428     else
2429         add_kbnode( sec_keyblock, new_kbnode(pkt) );
2430     /* insert/append to public keyblock */
2431     pkt = m_alloc_clear( sizeof *pkt );
2432     pkt->pkttype = PKT_USER_ID;
2433     pkt->pkt.user_id = uid;
2434     node = new_kbnode(pkt);
2435     if( pub_where )
2436         insert_kbnode( pub_where, node, 0 );
2437     else
2438         add_kbnode( pub_keyblock, node );
2439     pkt = m_alloc_clear( sizeof *pkt );
2440     pkt->pkttype = PKT_SIGNATURE;
2441     pkt->pkt.signature = copy_signature(NULL, sig);
2442     if( pub_where )
2443         insert_kbnode( node, new_kbnode(pkt), 0 );
2444     else
2445         add_kbnode( pub_keyblock, new_kbnode(pkt) );
2446     return 1;
2447 }
2448
2449
2450 /****************
2451  * Remove all selceted userids from the keyrings
2452  */
2453 static void
2454 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
2455 {
2456     KBNODE node;
2457     int selected=0;
2458
2459     for( node = pub_keyblock; node; node = node->next ) {
2460         if( node->pkt->pkttype == PKT_USER_ID ) {
2461             selected = node->flag & NODFLG_SELUID;
2462             if( selected ) {
2463                 /* Only cause a trust update if we delete a
2464                    non-revoked user id */
2465                 if(!node->pkt->pkt.user_id->is_revoked)
2466                   update_trust=1;
2467                 delete_kbnode( node );
2468                 if( sec_keyblock ) {
2469                     KBNODE snode;
2470                     int s_selected = 0;
2471                     PKT_user_id *uid = node->pkt->pkt.user_id;
2472                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2473                         if( snode->pkt->pkttype == PKT_USER_ID ) {
2474                             PKT_user_id *suid = snode->pkt->pkt.user_id;
2475
2476                             s_selected =
2477                                 (uid->len == suid->len
2478                                  && !memcmp( uid->name, suid->name, uid->len));
2479                             if( s_selected )
2480                                 delete_kbnode( snode );
2481                         }
2482                         else if( s_selected
2483                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2484                             delete_kbnode( snode );
2485                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
2486                             s_selected = 0;
2487                     }
2488                 }
2489             }
2490         }
2491         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2492             delete_kbnode( node );
2493         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2494             selected = 0;
2495     }
2496     commit_kbnode( &pub_keyblock );
2497     if( sec_keyblock )
2498         commit_kbnode( &sec_keyblock );
2499 }
2500
2501
2502 static int
2503 menu_delsig( KBNODE pub_keyblock )
2504 {
2505     KBNODE node;
2506     PKT_user_id *uid = NULL;
2507     int changed=0;
2508
2509     for( node = pub_keyblock; node; node = node->next ) {
2510         if( node->pkt->pkttype == PKT_USER_ID ) {
2511             uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
2512         }
2513         else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2514            int okay, valid, selfsig, inv_sig, no_key, other_err;
2515
2516             tty_printf("uid  ");
2517             tty_print_utf8_string( uid->name, uid->len );
2518             tty_printf("\n");
2519
2520            okay = inv_sig = no_key = other_err = 0;
2521             valid = print_and_check_one_sig( pub_keyblock, node,
2522                                             &inv_sig, &no_key, &other_err,
2523                                             &selfsig, 1 );
2524
2525            if( valid ) {
2526                okay = cpr_get_answer_yes_no_quit(
2527                    "keyedit.delsig.valid",
2528                    _("Delete this good signature? (y/N/q)"));
2529
2530                /* Only update trust if we delete a good signature.
2531                   The other two cases do not affect trust. */
2532                if(okay)
2533                  update_trust=1;
2534            }
2535            else if( inv_sig || other_err )
2536                okay = cpr_get_answer_yes_no_quit(
2537                    "keyedit.delsig.invalid",
2538                    _("Delete this invalid signature? (y/N/q)"));
2539            else if( no_key )
2540                okay = cpr_get_answer_yes_no_quit(
2541                    "keyedit.delsig.unknown",
2542                    _("Delete this unknown signature? (y/N/q)"));
2543
2544             if( okay == -1 )
2545                 break;
2546            if( okay && selfsig && !cpr_get_answer_is_yes(
2547                                "keyedit.delsig.selfsig",
2548                               _("Really delete this self-signature? (y/N)") ))
2549                 okay = 0;
2550             if( okay ) {
2551                 delete_kbnode( node );
2552                 changed++;
2553             }
2554
2555         }
2556         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2557             uid = NULL;
2558     }
2559
2560     if( changed ) {
2561         commit_kbnode( &pub_keyblock );
2562         tty_printf( changed == 1? _("Deleted %d signature.\n")
2563                                 : _("Deleted %d signatures.\n"), changed );
2564     }
2565     else
2566         tty_printf( _("Nothing deleted.\n") );
2567
2568     return changed;
2569 }
2570
2571
2572 /****************
2573  * Remove some of the secondary keys
2574  */
2575 static void
2576 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
2577 {
2578     KBNODE node;
2579     int selected=0;
2580
2581     for( node = pub_keyblock; node; node = node->next ) {
2582         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2583             selected = node->flag & NODFLG_SELKEY;
2584             if( selected ) {
2585                 delete_kbnode( node );
2586                 if( sec_keyblock ) {
2587                     KBNODE snode;
2588                     int s_selected = 0;
2589                     u32 ki[2];
2590
2591                     keyid_from_pk( node->pkt->pkt.public_key, ki );
2592                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2593                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2594                             u32 ki2[2];
2595
2596                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
2597                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
2598                             if( s_selected )
2599                                 delete_kbnode( snode );
2600                         }
2601                         else if( s_selected
2602                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2603                             delete_kbnode( snode );
2604                         else
2605                             s_selected = 0;
2606                     }
2607                 }
2608             }
2609         }
2610         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2611             delete_kbnode( node );
2612         else
2613             selected = 0;
2614     }
2615     commit_kbnode( &pub_keyblock );
2616     if( sec_keyblock )
2617         commit_kbnode( &sec_keyblock );
2618
2619     /* No need to set update_trust here since signing keys are no
2620        longer used to certify other keys, so there is no change in
2621        trust when revoking/removing them */
2622 }
2623
2624
2625 /****************
2626  * Ask for a new revoker, do the selfsignature and put it into
2627  * both keyblocks.
2628  * Return true if there is a new revoker
2629  */
2630 static int
2631 menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
2632 {
2633   PKT_public_key *pk=NULL,*revoker_pk=NULL;
2634   PKT_secret_key *sk=NULL;
2635   PKT_signature *sig=NULL;
2636   PACKET *pkt;
2637   struct revocation_key revkey;
2638   size_t fprlen;
2639   int rc;
2640
2641   assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
2642   assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
2643
2644   pk=pub_keyblock->pkt->pkt.public_key;
2645
2646   if(pk->numrevkeys==0 && pk->version==3)
2647     {
2648       /* It is legal but bad for compatibility to add a revoker to a
2649          v3 key as it means that PGP2 will not be able to use that key
2650          anymore.  Also, PGP may not expect a revoker on a v3 key.
2651          Don't bother to ask this if the key already has a revoker -
2652          any damage has already been done at that point. -dms */
2653       if(opt.expert)
2654         {
2655           tty_printf(_("WARNING: This is a PGP 2.x-style key.  "
2656                        "Adding a designated revoker may cause\n"
2657                        "         some versions of PGP to reject this key.\n"));
2658
2659           if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay",
2660                                     _("Are you sure you still want "
2661                                       "to add it? (y/N) ")))
2662             return 0;
2663         }
2664       else
2665         {
2666           tty_printf(_("You may not add a designated revoker to "
2667                        "a PGP 2.x-style key.\n"));
2668           return 0;
2669         }
2670     }
2671
2672   sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
2673
2674   for(;;)
2675     {
2676       char *answer;
2677       u32 keyid[2];
2678       char *p;
2679       size_t n;
2680
2681       if(revoker_pk)
2682         free_public_key(revoker_pk);
2683
2684       revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
2685
2686       tty_printf("\n");
2687
2688       answer=cpr_get_utf8("keyedit.add_revoker",
2689                           _("Enter the user ID of the designated revoker: "));
2690       if(answer[0]=='\0' || answer[0]=='\004')
2691         {
2692           m_free(answer);
2693           goto fail;
2694         }
2695
2696       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
2697
2698       if(rc)
2699         {
2700           log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
2701           m_free(answer);
2702           continue;
2703         }
2704
2705       m_free(answer);
2706
2707       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
2708       if(fprlen!=20)
2709         {
2710           log_error(_("cannot appoint a PGP 2.x style key as a "
2711                       "designated revoker\n"));
2712           continue;
2713         }
2714
2715       revkey.class=0x80;
2716       if(sensitive)
2717         revkey.class|=0x40;
2718       revkey.algid=revoker_pk->pubkey_algo;
2719
2720       if(cmp_public_keys(revoker_pk,pk)==0)
2721         {
2722           /* This actually causes no harm (after all, a key that
2723              designates itself as a revoker is the same as a
2724              regular key), but it's easy enough to check. */
2725           log_error(_("you cannot appoint a key as its own "
2726                       "designated revoker\n"));
2727
2728           continue;
2729         }
2730
2731       keyid_from_pk(pk,NULL);
2732
2733       /* Does this revkey already exist? */
2734       if(!pk->revkey && pk->numrevkeys)
2735         BUG();
2736       else
2737         {
2738           int i;
2739
2740           for(i=0;i<pk->numrevkeys;i++)
2741             {
2742               if(memcmp(&pk->revkey[i],&revkey,
2743                         sizeof(struct revocation_key))==0)
2744                 {
2745                   char buf[50];
2746
2747                   log_error(_("this key has already been designated "
2748                               "as a revoker\n"));
2749
2750                   sprintf(buf,"%08lX%08lX",
2751                           (ulong)pk->keyid[0],(ulong)pk->keyid[1]);
2752                   write_status_text(STATUS_ALREADY_SIGNED,buf);
2753
2754                   break;
2755                 }
2756             }
2757
2758           if(i<pk->numrevkeys)
2759             continue;
2760         }
2761
2762       keyid_from_pk(revoker_pk,keyid);
2763
2764       tty_printf("\npub   %4u%c/%08lX %s   ",
2765                  nbits_from_pk( revoker_pk ),
2766                  pubkey_letter( revoker_pk->pubkey_algo ),
2767                  (ulong)keyid[1], datestr_from_pk(pk) );
2768
2769       p = get_user_id( keyid, &n );
2770       tty_print_utf8_string( p, n );
2771       m_free(p);
2772       tty_printf("\n");
2773       print_fingerprint(revoker_pk,NULL,2);
2774       tty_printf("\n");
2775
2776       tty_printf(_("WARNING: appointing a key as a designated revoker "
2777                    "cannot be undone!\n"));
2778
2779       tty_printf("\n");
2780
2781       if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
2782                                 _("Are you sure you want to appoint this "
2783                                   "key as a designated revoker? (y/N): ")))
2784         continue;
2785
2786       free_public_key(revoker_pk);
2787       revoker_pk=NULL;
2788       break;
2789     }
2790
2791   /* The 1F signature must be at least v4 to carry the revocation key
2792      subpacket. */
2793   rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0,
2794                            keygen_add_revkey,&revkey );
2795   if( rc )
2796     {
2797       log_error("signing failed: %s\n", g10_errstr(rc) );
2798       goto fail;
2799     }
2800
2801   free_secret_key(sk);
2802   sk=NULL;
2803
2804   /* insert into secret keyblock */
2805   pkt = m_alloc_clear( sizeof *pkt );
2806   pkt->pkttype = PKT_SIGNATURE;
2807   pkt->pkt.signature = copy_signature(NULL, sig);
2808   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2809
2810   /* insert into public keyblock */
2811   pkt = m_alloc_clear( sizeof *pkt );
2812   pkt->pkttype = PKT_SIGNATURE;
2813   pkt->pkt.signature = sig;
2814   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2815
2816   return 1;
2817
2818  fail:
2819   if(sk)
2820     free_secret_key(sk);
2821   if(sig)
2822     free_seckey_enc(sig);
2823   if(revoker_pk)
2824     free_public_key(revoker_pk);
2825
2826   return 0;
2827 }
2828
2829
2830 static int
2831 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
2832 {
2833     int n1, signumber, rc;
2834     u32 expiredate;
2835     int mainkey=0;
2836     PKT_secret_key *sk;    /* copy of the main sk */
2837     PKT_public_key *main_pk, *sub_pk;
2838     PKT_user_id *uid;
2839     KBNODE node;
2840     u32 keyid[2];
2841
2842     if( count_selected_keys( sec_keyblock ) ) {
2843         tty_printf(_("Please remove selections from the secret keys.\n"));
2844         return 0;
2845     }
2846
2847     n1 = count_selected_keys( pub_keyblock );
2848     if( n1 > 1 ) {
2849         tty_printf(_("Please select at most one secondary key.\n"));
2850         return 0;
2851     }
2852     else if( n1 )
2853         tty_printf(_("Changing expiration time for a secondary key.\n"));
2854     else {
2855         tty_printf(_("Changing expiration time for the primary key.\n"));
2856         mainkey=1;
2857     }
2858
2859     no_primary_warning(pub_keyblock,0);
2860
2861     expiredate = ask_expiredate();
2862     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2863     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2864
2865     /* Now we can actually change the self signature(s) */
2866     main_pk = sub_pk = NULL;
2867     uid = NULL;
2868     signumber = 0;
2869     for( node=pub_keyblock; node; node = node->next ) {
2870         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2871             main_pk = node->pkt->pkt.public_key;
2872             keyid_from_pk( main_pk, keyid );
2873             main_pk->expiredate = expiredate;
2874         }
2875         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2876                  && (node->flag & NODFLG_SELKEY ) ) {
2877             sub_pk = node->pkt->pkt.public_key;
2878             sub_pk->expiredate = expiredate;
2879         }
2880         else if( node->pkt->pkttype == PKT_USER_ID )
2881             uid = node->pkt->pkt.user_id;
2882         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
2883                  && ( mainkey || sub_pk ) ) {
2884             PKT_signature *sig = node->pkt->pkt.signature;
2885             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2886                 && ( (mainkey && uid
2887                       && uid->created && (sig->sig_class&~3) == 0x10)
2888                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
2889                 /* this is a selfsignature which is to be replaced */
2890                 PKT_signature *newsig;
2891                 PACKET *newpkt;
2892                 KBNODE sn;
2893                 int signumber2 = 0;
2894
2895                 signumber++;
2896
2897                 if( (mainkey && main_pk->version < 4)
2898                     || (!mainkey && sub_pk->version < 4 ) ) {
2899                     log_info(_(
2900                         "You can't change the expiration date of a v3 key\n"));
2901                     free_secret_key( sk );
2902                     return 0;
2903                 }
2904
2905                 /* find the corresponding secret self-signature */
2906                 for( sn=sec_keyblock; sn; sn = sn->next ) {
2907                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
2908                         PKT_signature *b = sn->pkt->pkt.signature;
2909                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
2910                             && sig->sig_class == b->sig_class
2911                             && ++signumber2 == signumber )
2912                             break;
2913                     }
2914                 }
2915                 if( !sn )
2916                     log_info(_("No corresponding signature in secret ring\n"));
2917
2918                 if( mainkey )
2919                   rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL,
2920                                             sk, keygen_add_key_expire, main_pk);
2921                 else
2922                   rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk,
2923                                             sk, keygen_add_key_expire, sub_pk );
2924                 if( rc ) {
2925                     log_error("make_keysig_packet failed: %s\n",
2926                                                     g10_errstr(rc));
2927                     free_secret_key( sk );
2928                     return 0;
2929                 }
2930                 /* replace the packet */
2931                 newpkt = m_alloc_clear( sizeof *newpkt );
2932                 newpkt->pkttype = PKT_SIGNATURE;
2933                 newpkt->pkt.signature = newsig;
2934                 free_packet( node->pkt );
2935                 m_free( node->pkt );
2936                 node->pkt = newpkt;
2937                 if( sn ) {
2938                     newpkt = m_alloc_clear( sizeof *newpkt );
2939                     newpkt->pkttype = PKT_SIGNATURE;
2940                     newpkt->pkt.signature = copy_signature( NULL, newsig );
2941                     free_packet( sn->pkt );
2942                     m_free( sn->pkt );
2943                     sn->pkt = newpkt;
2944                 }
2945                 sub_pk = NULL;
2946             }
2947         }
2948     }
2949
2950     free_secret_key( sk );
2951     update_trust=1;
2952     return 1;
2953 }
2954
2955 static int
2956 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
2957 {
2958     byte buf[1];
2959
2960     /* first clear all primary uid flags so that we are sure none are
2961      * lingering around */
2962     delete_sig_subpkt (sig->hashed,   SIGSUBPKT_PRIMARY_UID);
2963     delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
2964
2965     /* if opaque is set,we want to set the primary id */
2966     if (opaque) { 
2967         buf[0] = 1;
2968         build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 );
2969     }
2970
2971     return 0;
2972 }
2973
2974
2975 /*
2976  * Set the primary uid flag for the selected UID.  We will also reset
2977  * all other primary uid flags.  For this to work with have to update
2978  * all the signature timestamps.  If we would do this with the current
2979  * time, we lose quite a lot of information, so we use a a kludge to
2980  * do this: Just increment the timestamp by one second which is
2981  * sufficient to updated a signature during import.
2982  */
2983 static int
2984 menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
2985 {
2986     PKT_secret_key *sk;    /* copy of the main sk */
2987     PKT_public_key *main_pk;
2988     PKT_user_id *uid;
2989     KBNODE node;
2990     u32 keyid[2];
2991     int selected;
2992     int attribute = 0;
2993     int modified = 0;
2994
2995     if ( count_selected_uids (pub_keyblock) != 1 ) {
2996         tty_printf(_("Please select exactly one user ID.\n"));
2997         return 0;
2998     }
2999
3000     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
3001     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
3002
3003     /* Now we can actually change the self signature(s) */
3004     main_pk = NULL;
3005     uid = NULL;
3006     selected = 0;
3007
3008     /* Is our selected uid an attribute packet? */
3009     for ( node=pub_keyblock; node; node = node->next )
3010       if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
3011         attribute = (node->pkt->pkt.user_id->attrib_data!=NULL);
3012
3013     for ( node=pub_keyblock; node; node = node->next ) {
3014         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
3015             break; /* ready */
3016
3017         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
3018             main_pk = node->pkt->pkt.public_key;
3019             keyid_from_pk( main_pk, keyid );
3020         }
3021         else if ( node->pkt->pkttype == PKT_USER_ID ) {
3022             uid = node->pkt->pkt.user_id;
3023             selected = node->flag & NODFLG_SELUID;
3024         }
3025         else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) {
3026             PKT_signature *sig = node->pkt->pkt.signature;
3027             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
3028                 && (uid && (sig->sig_class&~3) == 0x10)
3029                 && attribute == (uid->attrib_data!=NULL)) {
3030               if(sig->version < 4) {
3031                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
3032
3033                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
3034                          user);
3035                 m_free(user);
3036               }
3037               else {
3038                 /* This is a selfsignature which is to be replaced.
3039                    We can just ignore v3 signatures because they are
3040                    not able to carry the primary ID flag.  We also
3041                    ignore self-sigs on user IDs that are not of the
3042                    same type that we are making primary.  That is, if
3043                    we are making a user ID primary, we alter user IDs.
3044                    If we are making an attribute packet primary, we
3045                    alter attribute packets. */
3046
3047                 /* FIXME: We must make sure that we only have one
3048                    self-signature per user ID here (not counting
3049                    revocations) */
3050                 PKT_signature *newsig;
3051                 PACKET *newpkt;
3052                 const byte *p;
3053                 int action;
3054
3055                 /* see whether this signature has the primary UID flag */
3056                 p = parse_sig_subpkt (sig->hashed,
3057                                       SIGSUBPKT_PRIMARY_UID, NULL );
3058                 if ( !p )
3059                     p = parse_sig_subpkt (sig->unhashed,
3060                                           SIGSUBPKT_PRIMARY_UID, NULL );
3061                 if ( p && *p ) /* yes */
3062                     action = selected? 0 : -1;
3063                 else /* no */
3064                     action = selected? 1 : 0;
3065
3066                 if (action) {
3067                     int rc = update_keysig_packet (&newsig, sig,
3068                                                main_pk, uid, NULL,
3069                                                sk,
3070                                                change_primary_uid_cb,
3071                                                action > 0? "x":NULL );
3072                     if( rc ) {
3073                         log_error ("update_keysig_packet failed: %s\n",
3074                                    g10_errstr(rc));
3075                         free_secret_key( sk );
3076                         return 0;
3077                     }
3078                     /* replace the packet */
3079                     newpkt = m_alloc_clear( sizeof *newpkt );
3080                     newpkt->pkttype = PKT_SIGNATURE;
3081                     newpkt->pkt.signature = newsig;
3082                     free_packet( node->pkt );
3083                     m_free( node->pkt );
3084                     node->pkt = newpkt;
3085                     modified = 1;
3086                 }
3087               }
3088             }
3089         }
3090     }
3091
3092     free_secret_key( sk );
3093     return modified;
3094 }
3095
3096
3097 /* 
3098  * Set preferences to new values for the selected user IDs
3099  */
3100 static int
3101 menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
3102 {
3103     PKT_secret_key *sk;    /* copy of the main sk */
3104     PKT_public_key *main_pk;
3105     PKT_user_id *uid;
3106     KBNODE node;
3107     u32 keyid[2];
3108     int selected, select_all;
3109     int modified = 0;
3110
3111     no_primary_warning(pub_keyblock,1);
3112
3113     select_all = !count_selected_uids (pub_keyblock);
3114
3115     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
3116     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
3117
3118     /* Now we can actually change the self signature(s) */
3119     main_pk = NULL;
3120     uid = NULL;
3121     selected = 0;
3122     for ( node=pub_keyblock; node; node = node->next ) {
3123         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
3124             break; /* ready */
3125
3126         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
3127             main_pk = node->pkt->pkt.public_key;
3128             keyid_from_pk( main_pk, keyid );
3129         }
3130         else if ( node->pkt->pkttype == PKT_USER_ID ) {
3131             uid = node->pkt->pkt.user_id;
3132             selected = select_all || (node->flag & NODFLG_SELUID);
3133         }
3134         else if ( main_pk && uid && selected
3135                   && node->pkt->pkttype == PKT_SIGNATURE ) {
3136             PKT_signature *sig = node->pkt->pkt.signature;
3137             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
3138                  && (uid && (sig->sig_class&~3) == 0x10) ) {
3139               if( sig->version < 4 ) {
3140                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
3141
3142                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
3143                          user);
3144                 m_free(user);
3145               }
3146               else {
3147                 /* This is a selfsignature which is to be replaced 
3148                  * We have to ignore v3 signatures because they are
3149                  * not able to carry the preferences */
3150                 PKT_signature *newsig;
3151                 PACKET *newpkt;
3152                 int rc;
3153
3154                 rc = update_keysig_packet (&newsig, sig,
3155                                            main_pk, uid, NULL,
3156                                            sk,
3157                                            keygen_upd_std_prefs,
3158                                            NULL );
3159                 if( rc ) {
3160                     log_error ("update_keysig_packet failed: %s\n",
3161                                g10_errstr(rc));
3162                     free_secret_key( sk );
3163                     return 0;
3164                 }
3165                 /* replace the packet */
3166                 newpkt = m_alloc_clear( sizeof *newpkt );
3167                 newpkt->pkttype = PKT_SIGNATURE;
3168                 newpkt->pkt.signature = newsig;
3169                 free_packet( node->pkt );
3170                 m_free( node->pkt );
3171                 node->pkt = newpkt;
3172                 modified = 1;
3173               }
3174             }
3175         }
3176     }
3177     
3178     free_secret_key( sk );
3179     return modified;
3180 }
3181
3182
3183 static int
3184 menu_set_keyserver_url (KBNODE pub_keyblock, KBNODE sec_keyblock )
3185 {
3186     PKT_secret_key *sk;    /* copy of the main sk */
3187     PKT_public_key *main_pk;
3188     PKT_user_id *uid;
3189     KBNODE node;
3190     u32 keyid[2];
3191     int selected, select_all;
3192     int modified = 0;
3193     char *answer;
3194
3195     no_primary_warning(pub_keyblock,1);
3196
3197     answer=cpr_get_utf8("keyedit.add_keyserver",
3198                         _("Enter your preferred keyserver URL: "));
3199     if(answer[0]=='\0' || answer[0]=='\004')
3200       {
3201         m_free(answer);
3202         return 0;
3203       }
3204
3205     select_all = !count_selected_uids (pub_keyblock);
3206
3207     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
3208     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
3209
3210     /* Now we can actually change the self signature(s) */
3211     main_pk = NULL;
3212     uid = NULL;
3213     selected = 0;
3214     for ( node=pub_keyblock; node; node = node->next ) {
3215         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
3216             break; /* ready */
3217
3218         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
3219             main_pk = node->pkt->pkt.public_key;
3220             keyid_from_pk( main_pk, keyid );
3221         }
3222         else if ( node->pkt->pkttype == PKT_USER_ID ) {
3223             uid = node->pkt->pkt.user_id;
3224             selected = select_all || (node->flag & NODFLG_SELUID);
3225         }
3226         else if ( main_pk && uid && selected
3227                   && node->pkt->pkttype == PKT_SIGNATURE ) {
3228             PKT_signature *sig = node->pkt->pkt.signature;
3229             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
3230                  && (uid && (sig->sig_class&~3) == 0x10) ) {
3231               if( sig->version < 4 ) {
3232                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
3233
3234                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
3235                          user);
3236                 m_free(user);
3237               }
3238               else {
3239                 /* This is a selfsignature which is to be replaced 
3240                  * We have to ignore v3 signatures because they are
3241                  * not able to carry the preferences */
3242                 PKT_signature *newsig;
3243                 PACKET *newpkt;
3244                 int rc;
3245
3246                 rc = update_keysig_packet (&newsig, sig,
3247                                            main_pk, uid, NULL,
3248                                            sk,
3249                                            keygen_add_keyserver_url,
3250                                            answer );
3251                 if( rc ) {
3252                     log_error ("update_keysig_packet failed: %s\n",
3253                                g10_errstr(rc));
3254                     m_free(answer);
3255                     free_secret_key( sk );
3256                     return 0;
3257                 }
3258                 /* replace the packet */
3259                 newpkt = m_alloc_clear( sizeof *newpkt );
3260                 newpkt->pkttype = PKT_SIGNATURE;
3261                 newpkt->pkt.signature = newsig;
3262                 free_packet( node->pkt );
3263                 m_free( node->pkt );
3264                 node->pkt = newpkt;
3265                 modified = 1;
3266               }
3267             }
3268         }
3269     }
3270
3271     m_free(answer);
3272     free_secret_key( sk );
3273     return modified;
3274 }
3275
3276
3277 /****************
3278  * Select one user id or remove all selection if index is 0.
3279  * Returns: True if the selection changed;
3280  */
3281 static int
3282 menu_select_uid( KBNODE keyblock, int idx )
3283 {
3284     KBNODE node;
3285     int i;
3286
3287     /* first check that the index is valid */
3288     if( idx ) {
3289         for( i=0, node = keyblock; node; node = node->next ) {
3290             if( node->pkt->pkttype == PKT_USER_ID ) {
3291                 if( ++i == idx )
3292                     break;
3293             }
3294         }
3295         if( !node ) {
3296             tty_printf(_("No user ID with index %d\n"), idx );
3297             return 0;
3298         }
3299     }
3300     else { /* reset all */
3301         for( i=0, node = keyblock; node; node = node->next ) {
3302             if( node->pkt->pkttype == PKT_USER_ID )
3303                 node->flag &= ~NODFLG_SELUID;
3304         }
3305         return 1;
3306     }
3307     /* and toggle the new index */
3308     for( i=0, node = keyblock; node; node = node->next ) {
3309         if( node->pkt->pkttype == PKT_USER_ID ) {
3310             if( ++i == idx ) {
3311                 if( (node->flag & NODFLG_SELUID) )
3312                     node->flag &= ~NODFLG_SELUID;
3313                 else
3314                     node->flag |= NODFLG_SELUID;
3315             }
3316         }
3317     }
3318
3319     return 1;
3320 }
3321
3322 /****************
3323  * Select secondary keys
3324  * Returns: True if the selection changed;
3325  */
3326 static int
3327 menu_select_key( KBNODE keyblock, int idx )
3328 {
3329     KBNODE node;
3330     int i;
3331
3332     /* first check that the index is valid */
3333     if( idx ) {
3334         for( i=0, node = keyblock; node; node = node->next ) {
3335             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3336                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
3337                 if( ++i == idx )
3338                     break;
3339             }
3340         }
3341         if( !node ) {
3342             tty_printf(_("No secondary key with index %d\n"), idx );
3343             return 0;
3344         }
3345     }
3346     else { /* reset all */
3347         for( i=0, node = keyblock; node; node = node->next ) {
3348             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3349                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
3350                 node->flag &= ~NODFLG_SELKEY;
3351         }
3352         return 1;
3353     }
3354     /* and set the new index */
3355     for( i=0, node = keyblock; node; node = node->next ) {
3356         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3357             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
3358             if( ++i == idx ) {
3359                 if( (node->flag & NODFLG_SELKEY) )
3360                     node->flag &= ~NODFLG_SELKEY;
3361                 else
3362                     node->flag |= NODFLG_SELKEY;
3363             }
3364         }
3365     }
3366
3367     return 1;
3368 }
3369
3370
3371 static int
3372 count_uids_with_flag( KBNODE keyblock, unsigned flag )
3373 {
3374     KBNODE node;
3375     int i=0;
3376
3377     for( node = keyblock; node; node = node->next )
3378         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
3379             i++;
3380     return i;
3381 }
3382
3383 static int
3384 count_keys_with_flag( KBNODE keyblock, unsigned flag )
3385 {
3386     KBNODE node;
3387     int i=0;
3388
3389     for( node = keyblock; node; node = node->next )
3390         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3391               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
3392             && (node->flag & flag) )
3393             i++;
3394     return i;
3395 }
3396
3397 static int
3398 count_uids( KBNODE keyblock )
3399 {
3400     KBNODE node;
3401     int i=0;
3402
3403     for( node = keyblock; node; node = node->next )
3404         if( node->pkt->pkttype == PKT_USER_ID )
3405             i++;
3406     return i;
3407 }
3408
3409
3410 /****************
3411  * Returns true if there is at least one selected user id
3412  */
3413 static int
3414 count_selected_uids( KBNODE keyblock )
3415 {
3416     return count_uids_with_flag( keyblock, NODFLG_SELUID);
3417 }
3418
3419 static int
3420 count_selected_keys( KBNODE keyblock )
3421 {
3422     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
3423 }
3424
3425 /* returns how many real (i.e. not attribute) uids are unmarked */
3426 static int
3427 real_uids_left( KBNODE keyblock )
3428 {
3429   KBNODE node;
3430   int real=0;
3431
3432   for(node=keyblock;node;node=node->next)
3433     if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) &&
3434        !node->pkt->pkt.user_id->attrib_data)
3435       real++;
3436
3437   return real;
3438 }
3439
3440 /*
3441  * Ask whether the signature should be revoked.  If the user commits this,
3442  * flag bit MARK_A is set on the signature and the user ID.
3443  */
3444 static void
3445 ask_revoke_sig( KBNODE keyblock, KBNODE node )
3446 {
3447     int doit=0;
3448     PKT_signature *sig = node->pkt->pkt.signature;
3449     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3450
3451     if( !unode ) {
3452         log_error("Oops: no user ID for signature\n");
3453         return;
3454     }
3455
3456     tty_printf(_("user ID: \""));
3457     tty_print_utf8_string( unode->pkt->pkt.user_id->name,
3458                            unode->pkt->pkt.user_id->len );
3459
3460     if(sig->flags.exportable)
3461       tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
3462                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3463     else
3464       tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"),
3465                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3466
3467     if(sig->flags.expired)
3468       {
3469         tty_printf(_("This signature expired on %s.\n"),
3470                    expirestr_from_sig(sig));
3471         /* Use a different question so we can have different help text */
3472         doit=cpr_get_answer_is_yes("ask_revoke_sig.expired",
3473                         _("Are you sure you still want to revoke it? (y/N) "));
3474       }
3475     else
3476       doit=cpr_get_answer_is_yes("ask_revoke_sig.one",
3477               _("Create a revocation certificate for this signature? (y/N) "));
3478
3479     if(doit) {
3480       node->flag |= NODFLG_MARK_A;
3481       unode->flag |= NODFLG_MARK_A;
3482     }
3483 }
3484
3485 /****************
3486  * Display all user ids of the current public key together with signatures
3487  * done by one of our keys.  Then walk over all this sigs and ask the user
3488  * whether he wants to revoke this signature.
3489  * Return: True when the keyblock has changed.
3490  */
3491 static int
3492 menu_revsig( KBNODE keyblock )
3493 {
3494     PKT_signature *sig;
3495     PKT_public_key *primary_pk;
3496     KBNODE node;
3497     int changed = 0;
3498     int rc, any, skip=1, all=!count_selected_uids(keyblock);
3499     struct revocation_reason_info *reason = NULL;
3500
3501     /* FIXME: detect duplicates here  */
3502     tty_printf(_("You have signed these user IDs:\n"));
3503     for( node = keyblock; node; node = node->next ) {
3504         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
3505         if( node->pkt->pkttype == PKT_USER_ID ) {
3506             if( node->flag&NODFLG_SELUID || all ) {
3507               PKT_user_id *uid = node->pkt->pkt.user_id;
3508               /* Hmmm: Should we show only UIDs with a signature? */
3509               tty_printf("     ");
3510               tty_print_utf8_string( uid->name, uid->len );
3511               tty_printf("\n");
3512               skip=0;
3513             }
3514             else
3515               skip=1;
3516         }
3517         else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
3518                 && ((sig = node->pkt->pkt.signature),
3519                      !seckey_available(sig->keyid)  ) ) {
3520             if( (sig->sig_class&~3) == 0x10 ) {
3521                 tty_printf(_("   signed by %08lX at %s%s%s\n"),
3522                            (ulong)sig->keyid[1], datestr_from_sig(sig),
3523                            sig->flags.exportable?"":" (non-exportable)",
3524                            sig->flags.revocable?"":" (non-revocable)");
3525                 if(sig->flags.revocable)
3526                   node->flag |= NODFLG_SELSIG;
3527             }
3528             else if( sig->sig_class == 0x30 ) {
3529                 tty_printf(_("   revoked by %08lX at %s\n"),
3530                             (ulong)sig->keyid[1], datestr_from_sig(sig) );
3531             }
3532         }
3533     }
3534
3535     /* ask */
3536     for( node = keyblock; node; node = node->next ) {
3537         if( !(node->flag & NODFLG_SELSIG) )
3538             continue;
3539         ask_revoke_sig( keyblock, node );
3540     }
3541
3542     /* present selected */
3543     any = 0;
3544     for( node = keyblock; node; node = node->next ) {
3545         if( !(node->flag & NODFLG_MARK_A) )
3546             continue;
3547         if( !any ) {
3548             any = 1;
3549             tty_printf(_("You are about to revoke these signatures:\n"));
3550         }
3551         if( node->pkt->pkttype == PKT_USER_ID ) {
3552             PKT_user_id *uid = node->pkt->pkt.user_id;
3553             tty_printf("     ");
3554             tty_print_utf8_string( uid->name, uid->len );
3555             tty_printf("\n");
3556         }
3557         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
3558             sig = node->pkt->pkt.signature;
3559             tty_printf(_("   signed by %08lX at %s%s\n"),
3560                        (ulong)sig->keyid[1], datestr_from_sig(sig),
3561                        sig->flags.exportable?"":_(" (non-exportable)") );
3562         }
3563     }
3564     if( !any )
3565         return 0; /* none selected */
3566
3567     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
3568          _("Really create the revocation certificates? (y/N) ")) )
3569         return 0; /* forget it */
3570
3571     reason = ask_revocation_reason( 0, 1, 0 );
3572     if( !reason ) { /* user decided to cancel */
3573         return 0;
3574     }
3575
3576     /* now we can sign the user ids */
3577   reloop: /* (must use this, because we are modifing the list) */
3578     primary_pk = keyblock->pkt->pkt.public_key;
3579     for( node=keyblock; node; node = node->next ) {
3580         KBNODE unode;
3581         PACKET *pkt;
3582         struct sign_attrib attrib;
3583         PKT_secret_key *sk;
3584
3585         if( !(node->flag & NODFLG_MARK_A)
3586             || node->pkt->pkttype != PKT_SIGNATURE )
3587             continue;
3588         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3589         assert( unode ); /* we already checked this */
3590
3591         memset( &attrib, 0, sizeof attrib );
3592         attrib.reason = reason;
3593         attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
3594
3595         node->flag &= ~NODFLG_MARK_A;
3596         sk = m_alloc_secure_clear( sizeof *sk );
3597         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
3598             log_info(_("no secret key\n"));
3599             continue;
3600         }
3601         rc = make_keysig_packet( &sig, primary_pk,
3602                                        unode->pkt->pkt.user_id,
3603                                        NULL,
3604                                        sk,
3605                                        0x30, 0, 0, 0, 0,
3606                                        sign_mk_attrib,
3607                                        &attrib );
3608         free_secret_key(sk);
3609         if( rc ) {
3610             log_error(_("signing failed: %s\n"), g10_errstr(rc));
3611             release_revocation_reason_info( reason );
3612             return changed;
3613         }
3614         changed = 1; /* we changed the keyblock */
3615         update_trust = 1;
3616         /* Are we revoking our own uid? */
3617         if(primary_pk->keyid[0]==sig->keyid[0] &&
3618            primary_pk->keyid[1]==sig->keyid[1])
3619           unode->pkt->pkt.user_id->is_revoked=1;
3620         pkt = m_alloc_clear( sizeof *pkt );
3621         pkt->pkttype = PKT_SIGNATURE;
3622         pkt->pkt.signature = sig;
3623         insert_kbnode( unode, new_kbnode(pkt), 0 );
3624         goto reloop;
3625     }
3626
3627     release_revocation_reason_info( reason );
3628     return changed;
3629 }
3630
3631 /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
3632    keyblock changed. */
3633 static int
3634 menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
3635 {
3636   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
3637   PKT_secret_key *sk = copy_secret_key( NULL,
3638                                         sec_keyblock->pkt->pkt.secret_key );
3639   KBNODE node;
3640   int changed = 0;
3641   int rc;
3642   struct revocation_reason_info *reason = NULL;
3643
3644   /* Note that this is correct as per the RFCs, but nevertheless
3645      somewhat meaningless in the real world.  1991 did define the 0x30
3646      sig class, but PGP 2.x did not actually implement it, so it would
3647      probably be safe to use v4 revocations everywhere. -ds */
3648
3649   for( node = pub_keyblock; node; node = node->next )
3650     if(pk->version>3 || (node->pkt->pkttype==PKT_USER_ID &&
3651                          node->pkt->pkt.user_id->selfsigversion>3))
3652       {
3653         if((reason = ask_revocation_reason( 0, 1, 4 )))
3654           break;
3655         else
3656           goto leave;
3657       }
3658
3659  reloop: /* (better this way because we are modifing the keyring) */
3660   for( node = pub_keyblock; node; node = node->next )
3661     if(node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
3662       {
3663         PKT_user_id *uid=node->pkt->pkt.user_id;
3664
3665         if(uid->is_revoked)
3666           {
3667             char *user=utf8_to_native(uid->name,uid->len,0);
3668             log_info(_("user ID \"%s\" is already revoked\n"),user);
3669             m_free(user);
3670           }
3671         else
3672           {
3673             PACKET *pkt;
3674             PKT_signature *sig;
3675             struct sign_attrib attrib;
3676             u32 timestamp=make_timestamp();
3677
3678             if(uid->created>=timestamp)
3679               {
3680                 /* Okay, this is a problem.  The user ID selfsig was
3681                    created in the future, so we need to warn the user and
3682                    set our revocation timestamp one second after that so
3683                    everything comes out clean. */
3684
3685                 log_info(_("WARNING: a user ID signature is dated %d"
3686                            " seconds in the future\n"),uid->created-timestamp);
3687
3688                 timestamp=uid->created+1;
3689               }
3690
3691             memset( &attrib, 0, sizeof attrib );
3692             attrib.reason = reason;
3693
3694             node->flag &= ~NODFLG_SELUID;
3695
3696             rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x30, 0,
3697                                      (reason==NULL)?3:0, timestamp, 0,
3698                                      sign_mk_attrib, &attrib );
3699             if( rc )
3700               {
3701                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3702                 goto leave;
3703               }
3704             else
3705               {
3706                 pkt = m_alloc_clear( sizeof *pkt );
3707                 pkt->pkttype = PKT_SIGNATURE;
3708                 pkt->pkt.signature = sig;
3709                 insert_kbnode( node, new_kbnode(pkt), 0 );
3710
3711                 /* If the trustdb has an entry for this key+uid then the
3712                    trustdb needs an update. */
3713                 if(!update_trust
3714                    && (get_validity(pk,uid)&TRUST_MASK)>=TRUST_UNDEFINED)
3715                   update_trust=1;
3716
3717                 changed = 1;
3718                 node->pkt->pkt.user_id->is_revoked=1;
3719
3720                 goto reloop;
3721               }
3722           }
3723       }
3724
3725   if(changed)
3726     commit_kbnode( &pub_keyblock );
3727
3728  leave:
3729   free_secret_key(sk);
3730   release_revocation_reason_info( reason );
3731   return changed;
3732 }
3733
3734 /****************
3735  * Revoke some of the secondary keys.
3736  * Hmmm: Should we add a revocation to the secret keyring too?
3737  *       Does its all make sense to duplicate most of the information?
3738  */
3739 static int
3740 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
3741 {
3742     PKT_public_key *mainpk;
3743     KBNODE node;
3744     int changed = 0;
3745     int rc;
3746     struct revocation_reason_info *reason = NULL;
3747
3748     reason = ask_revocation_reason( 1, 0, 0 );
3749     if( !reason ) { /* user decided to cancel */
3750         return 0;
3751     }
3752
3753   reloop: /* (better this way because we are modifing the keyring) */
3754     mainpk = pub_keyblock->pkt->pkt.public_key;
3755     for( node = pub_keyblock; node; node = node->next ) {
3756         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3757             && (node->flag & NODFLG_SELKEY) ) {
3758             PACKET *pkt;
3759             PKT_signature *sig;
3760             PKT_secret_key *sk;
3761             PKT_public_key *subpk = node->pkt->pkt.public_key;
3762             struct sign_attrib attrib;
3763
3764             memset( &attrib, 0, sizeof attrib );
3765             attrib.reason = reason;
3766
3767             node->flag &= ~NODFLG_SELKEY;
3768             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
3769             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk,
3770                                      0x28, 0, 0, 0, 0,
3771                                      sign_mk_attrib, &attrib );
3772             free_secret_key(sk);
3773             if( rc ) {
3774                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3775                 release_revocation_reason_info( reason );
3776                 return changed;
3777       &nb