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