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