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