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