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