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