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