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