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