* keyedit.c (print_and_check_one_sig): 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             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2051                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
2052                           (node->flag & NODFLG_SELKEY)? '*':' ',
2053                           nbits_from_pk( pk ),
2054                           pubkey_letter( pk->pubkey_algo ),
2055                           (ulong)keyid_from_pk(pk,NULL),
2056                           datestr_from_pk(pk),
2057                           expirestr_from_pk(pk) );
2058             tty_printf("\n");
2059
2060             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
2061               {
2062                 tty_printf("                     ");
2063                 tty_printf(_("trust: %-13s"), otrust);
2064                 tty_printf(_("validity: %s"), trust );
2065                 tty_printf("\n");
2066                 if( node->pkt->pkttype == PKT_PUBLIC_KEY
2067                     && (get_ownertrust (pk)&TRUST_FLAG_DISABLED))
2068                   {
2069                     tty_printf("*** ");
2070                     tty_printf(_("This key has been disabled"));
2071                     tty_printf("\n");
2072                   }
2073               }
2074
2075             if( node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr )
2076               {
2077                 print_fingerprint ( pk, NULL, 2 );
2078                 tty_printf("\n");
2079               }
2080         }
2081         else if( node->pkt->pkttype == PKT_SECRET_KEY
2082             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
2083             PKT_secret_key *sk = node->pkt->pkt.secret_key;
2084             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2085                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
2086                           (node->flag & NODFLG_SELKEY)? '*':' ',
2087                           nbits_from_sk( sk ),
2088                           pubkey_letter( sk->pubkey_algo ),
2089                           (ulong)keyid_from_sk(sk,NULL),
2090                           datestr_from_sk(sk),
2091                           expirestr_from_sk(sk) );
2092             tty_printf("\n");
2093         }
2094         else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
2095                  && node->pkt->pkt.signature->sig_class == 0x28       ) {
2096             PKT_signature *sig = node->pkt->pkt.signature;
2097
2098             rc = check_key_signature( keyblock, node, NULL );
2099             if( !rc )
2100                 tty_printf( _("rev! subkey has been revoked: %s\n"),
2101                             datestr_from_sig( sig ) );
2102             else if( rc == G10ERR_BAD_SIGN )
2103                 tty_printf( _("rev- faked revocation found\n") );
2104             else if( rc )
2105                 tty_printf( _("rev? problem checking revocation: %s\n"),
2106                                                          g10_errstr(rc) );
2107         }
2108     }
2109     
2110     assert(primary);
2111
2112     /* the user ids */
2113     i = 0;
2114     for( node = keyblock; node; node = node->next ) {
2115         if( node->pkt->pkttype == PKT_USER_ID ) {
2116             PKT_user_id *uid = node->pkt->pkt.user_id;
2117             ++i;
2118             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
2119                 if(opt.list_options&LIST_SHOW_VALIDITY)
2120                   tty_printf("[%8.8s] ",
2121                              trust_value_to_string(get_validity(primary,uid)));
2122                 if( only_marked )
2123                    tty_printf("     ");
2124                 else if( node->flag & NODFLG_SELUID )
2125                    tty_printf("(%d)* ", i);
2126                 else if( uid->is_primary )
2127                    tty_printf("(%d). ", i);
2128                 else
2129                    tty_printf("(%d)  ", i);
2130                 if ( uid->is_revoked )
2131                     tty_printf (_("[revoked] "));
2132                 if ( uid->is_expired )
2133                     tty_printf (_("[expired] "));
2134                 tty_print_utf8_string( uid->name, uid->len );
2135                 tty_printf("\n");
2136                 if( with_prefs )
2137                   {
2138                     if(pk_version>3 || uid->selfsigversion>3)
2139                       show_prefs (uid, with_prefs == 2);
2140                     else
2141                       tty_printf(_("There are no preferences on a "
2142                                    "PGP 2.x-style user ID.\n"));
2143                   }
2144             }
2145         }
2146     }
2147
2148     if (do_warn)
2149         tty_printf (_("Please note that the shown key validity "
2150                       "is not necessarily correct\n"
2151                       "unless you restart the program.\n")); 
2152
2153 }
2154
2155
2156 /* Display basic key information.  This fucntion is suitable to show
2157    information on the key without any dependencies on the trustdb or
2158    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
2159    a secret key.*/
2160 void
2161 show_basic_key_info ( KBNODE keyblock )
2162 {
2163   KBNODE node;
2164   int i;
2165
2166   /* The primary key */
2167   for (node = keyblock; node; node = node->next)
2168     {
2169       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
2170         {
2171           PKT_public_key *pk = node->pkt->pkt.public_key;
2172           
2173           /* Note, we use the same format string as in other show
2174              functions to make the translation job easier. */
2175           tty_printf (_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2176                       node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
2177                       ' ',
2178                       nbits_from_pk( pk ),
2179                       pubkey_letter( pk->pubkey_algo ),
2180                       (ulong)keyid_from_pk(pk,NULL),
2181                       datestr_from_pk(pk),
2182                       expirestr_from_pk(pk) );
2183           tty_printf("\n");
2184           print_fingerprint ( pk, NULL, 3 );
2185           tty_printf("\n");
2186         }
2187       else if (node->pkt->pkttype == PKT_SECRET_KEY)
2188         {
2189           PKT_secret_key *sk = node->pkt->pkt.secret_key;
2190           tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2191                      node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
2192                      ' ',
2193                      nbits_from_sk( sk ),
2194                      pubkey_letter( sk->pubkey_algo ),
2195                      (ulong)keyid_from_sk(sk,NULL),
2196                      datestr_from_sk(sk),
2197                      expirestr_from_sk(sk) );
2198           tty_printf("\n");
2199           print_fingerprint (NULL, sk, 3 );
2200           tty_printf("\n");
2201         }
2202     }
2203
2204   /* The user IDs. */
2205   for (i=0, node = keyblock; node; node = node->next)
2206     {
2207       if (node->pkt->pkttype == PKT_USER_ID)
2208         {
2209           PKT_user_id *uid = node->pkt->pkt.user_id;
2210           ++i;
2211      
2212           tty_printf ("     ");
2213           if (uid->is_revoked)
2214             tty_printf ("[revoked] ");
2215           if ( uid->is_expired )
2216             tty_printf ("[expired] ");
2217           tty_print_utf8_string (uid->name, uid->len);
2218           tty_printf ("\n");
2219         }
2220     }
2221 }
2222
2223 static void
2224 show_key_and_fingerprint( KBNODE keyblock )
2225 {
2226     KBNODE node;
2227     PKT_public_key *pk = NULL;
2228
2229     for( node = keyblock; node; node = node->next ) {
2230         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2231             pk = node->pkt->pkt.public_key;
2232             tty_printf("pub   %4u%c/%08lX %s ",
2233                           nbits_from_pk( pk ),
2234                           pubkey_letter( pk->pubkey_algo ),
2235                           (ulong)keyid_from_pk(pk,NULL),
2236                           datestr_from_pk(pk) );
2237         }
2238         else if( node->pkt->pkttype == PKT_USER_ID ) {
2239             PKT_user_id *uid = node->pkt->pkt.user_id;
2240             tty_print_utf8_string( uid->name, uid->len );
2241             break;
2242         }
2243     }
2244     tty_printf("\n");
2245     if( pk )
2246         print_fingerprint( pk, NULL, 2 );
2247 }
2248
2249
2250 /* Show a warning if no uids on the key have the primary uid flag
2251    set. */
2252 static void
2253 no_primary_warning(KBNODE keyblock, int uids)
2254 {
2255   KBNODE node;
2256   int select_all=1,have_uid=0,uid_count=0;
2257
2258   if(uids)
2259     select_all=!count_selected_uids(keyblock);
2260
2261   /* TODO: if we ever start behaving differently with a primary or
2262      non-primary attribute ID, we will need to check for attributes
2263      here as well. */
2264
2265   for(node=keyblock; node; node = node->next)
2266     {
2267       if(node->pkt->pkttype==PKT_USER_ID
2268          && node->pkt->pkt.user_id->attrib_data==NULL)
2269         {
2270           uid_count++;
2271
2272           if((select_all || (node->flag & NODFLG_SELUID))
2273              && node->pkt->pkt.user_id->is_primary==2)
2274             have_uid|=2;
2275           else
2276             have_uid|=1;
2277         }
2278     }
2279
2280   if(uid_count>1 && have_uid&1 && !(have_uid&2))
2281     log_info(_("WARNING: no user ID has been marked as primary.  This command "
2282                "may\n              cause a different user ID to become the assumed primary.\n"));
2283 }
2284
2285 /****************
2286  * Ask for a new user id, do the selfsignature and put it into
2287  * both keyblocks.
2288  * Return true if there is a new user id
2289  */
2290 static int
2291 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
2292 {
2293     PKT_user_id *uid;
2294     PKT_public_key *pk=NULL;
2295     PKT_secret_key *sk=NULL;
2296     PKT_signature *sig=NULL;
2297     PACKET *pkt;
2298     KBNODE node;
2299     KBNODE pub_where=NULL, sec_where=NULL;
2300     int rc;
2301
2302     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
2303         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
2304             pk = node->pkt->pkt.public_key;
2305         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2306             break;
2307     }
2308     if( !node ) /* no subkey */
2309         pub_where = NULL;
2310     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
2311         if( node->pkt->pkttype == PKT_SECRET_KEY )
2312             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2313         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
2314             break;
2315     }
2316     if( !node ) /* no subkey */
2317         sec_where = NULL;
2318     assert(pk && sk);
2319
2320     if(photo) {
2321       int hasattrib=0;
2322
2323       for( node = pub_keyblock; node; node = node->next )
2324         if( node->pkt->pkttype == PKT_USER_ID &&
2325             node->pkt->pkt.user_id->attrib_data!=NULL)
2326           {
2327             hasattrib=1;
2328             break;
2329           }
2330
2331       /* It is legal but bad for compatibility to add a photo ID to a
2332          v3 key as it means that PGP2 will not be able to use that key
2333          anymore.  Also, PGP may not expect a photo on a v3 key.
2334          Don't bother to ask this if the key already has a photo - any
2335          damage has already been done at that point. -dms */
2336       if(pk->version==3 && !hasattrib)
2337         {
2338           if(opt.expert)
2339             {
2340               tty_printf(_("WARNING: This is a PGP2-style key.  "
2341                            "Adding a photo ID may cause some versions\n"
2342                            "         of PGP to reject this key.\n"));
2343
2344               if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay",
2345                                         _("Are you sure you still want "
2346                                           "to add it? (y/N) ")))
2347                 return 0;
2348             }
2349           else
2350             {
2351               tty_printf(_("You may not add a photo ID to "
2352                            "a PGP2-style key.\n"));
2353               return 0;
2354             }
2355         }
2356
2357       uid = generate_photo_id(pk);
2358     } else
2359       uid = generate_user_id();
2360     if( !uid )
2361         return 0;
2362
2363     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
2364                              keygen_add_std_prefs, pk );
2365     free_secret_key( sk );
2366     if( rc ) {
2367         log_error("signing failed: %s\n", g10_errstr(rc) );
2368         free_user_id(uid);
2369         return 0;
2370     }
2371
2372     /* insert/append to secret keyblock */
2373     pkt = m_alloc_clear( sizeof *pkt );
2374     pkt->pkttype = PKT_USER_ID;
2375     pkt->pkt.user_id = scopy_user_id(uid);
2376     node = new_kbnode(pkt);
2377     if( sec_where )
2378         insert_kbnode( sec_where, node, 0 );
2379     else
2380         add_kbnode( sec_keyblock, node );
2381     pkt = m_alloc_clear( sizeof *pkt );
2382     pkt->pkttype = PKT_SIGNATURE;
2383     pkt->pkt.signature = copy_signature(NULL, sig);
2384     if( sec_where )
2385         insert_kbnode( node, new_kbnode(pkt), 0 );
2386     else
2387         add_kbnode( sec_keyblock, new_kbnode(pkt) );
2388     /* insert/append to public keyblock */
2389     pkt = m_alloc_clear( sizeof *pkt );
2390     pkt->pkttype = PKT_USER_ID;
2391     pkt->pkt.user_id = uid;
2392     node = new_kbnode(pkt);
2393     if( pub_where )
2394         insert_kbnode( pub_where, node, 0 );
2395     else
2396         add_kbnode( pub_keyblock, node );
2397     pkt = m_alloc_clear( sizeof *pkt );
2398     pkt->pkttype = PKT_SIGNATURE;
2399     pkt->pkt.signature = copy_signature(NULL, sig);
2400     if( pub_where )
2401         insert_kbnode( node, new_kbnode(pkt), 0 );
2402     else
2403         add_kbnode( pub_keyblock, new_kbnode(pkt) );
2404     return 1;
2405 }
2406
2407
2408 /****************
2409  * Remove all selceted userids from the keyrings
2410  */
2411 static void
2412 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
2413 {
2414     KBNODE node;
2415     int selected=0;
2416
2417     for( node = pub_keyblock; node; node = node->next ) {
2418         if( node->pkt->pkttype == PKT_USER_ID ) {
2419             selected = node->flag & NODFLG_SELUID;
2420             if( selected ) {
2421                 /* Only cause a trust update if we delete a
2422                    non-revoked user id */
2423                 if(!node->pkt->pkt.user_id->is_revoked)
2424                   update_trust=1;
2425                 delete_kbnode( node );
2426                 if( sec_keyblock ) {
2427                     KBNODE snode;
2428                     int s_selected = 0;
2429                     PKT_user_id *uid = node->pkt->pkt.user_id;
2430                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2431                         if( snode->pkt->pkttype == PKT_USER_ID ) {
2432                             PKT_user_id *suid = snode->pkt->pkt.user_id;
2433
2434                             s_selected =
2435                                 (uid->len == suid->len
2436                                  && !memcmp( uid->name, suid->name, uid->len));
2437                             if( s_selected )
2438                                 delete_kbnode( snode );
2439                         }
2440                         else if( s_selected
2441                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2442                             delete_kbnode( snode );
2443                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
2444                             s_selected = 0;
2445                     }
2446                 }
2447             }
2448         }
2449         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2450             delete_kbnode( node );
2451         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2452             selected = 0;
2453     }
2454     commit_kbnode( &pub_keyblock );
2455     if( sec_keyblock )
2456         commit_kbnode( &sec_keyblock );
2457 }
2458
2459
2460 static int
2461 menu_delsig( KBNODE pub_keyblock )
2462 {
2463     KBNODE node;
2464     PKT_user_id *uid = NULL;
2465     int changed=0;
2466
2467     for( node = pub_keyblock; node; node = node->next ) {
2468         if( node->pkt->pkttype == PKT_USER_ID ) {
2469             uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
2470         }
2471         else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2472            int okay, valid, selfsig, inv_sig, no_key, other_err;
2473
2474             tty_printf("uid  ");
2475             tty_print_utf8_string( uid->name, uid->len );
2476             tty_printf("\n");
2477
2478            okay = inv_sig = no_key = other_err = 0;
2479             valid = print_and_check_one_sig( pub_keyblock, node,
2480                                             &inv_sig, &no_key, &other_err,
2481                                             &selfsig, 1 );
2482
2483            if( valid ) {
2484                okay = cpr_get_answer_yes_no_quit(
2485                    "keyedit.delsig.valid",
2486                    _("Delete this good signature? (y/N/q)"));
2487
2488                /* Only update trust if we delete a good signature.
2489                   The other two cases do not affect trust. */
2490                if(okay)
2491                  update_trust=1;
2492            }
2493            else if( inv_sig || other_err )
2494                okay = cpr_get_answer_yes_no_quit(
2495                    "keyedit.delsig.invalid",
2496                    _("Delete this invalid signature? (y/N/q)"));
2497            else if( no_key )
2498                okay = cpr_get_answer_yes_no_quit(
2499                    "keyedit.delsig.unknown",
2500                    _("Delete this unknown signature? (y/N/q)"));
2501
2502             if( okay == -1 )
2503                 break;
2504            if( okay && selfsig && !cpr_get_answer_is_yes(
2505                                "keyedit.delsig.selfsig",
2506                               _("Really delete this self-signature? (y/N)") ))
2507                 okay = 0;
2508             if( okay ) {
2509                 delete_kbnode( node );
2510                 changed++;
2511             }
2512
2513         }
2514         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2515             uid = NULL;
2516     }
2517
2518     if( changed ) {
2519         commit_kbnode( &pub_keyblock );
2520         tty_printf( changed == 1? _("Deleted %d signature.\n")
2521                                 : _("Deleted %d signatures.\n"), changed );
2522     }
2523     else
2524         tty_printf( _("Nothing deleted.\n") );
2525
2526     return changed;
2527 }
2528
2529
2530 /****************
2531  * Remove some of the secondary keys
2532  */
2533 static void
2534 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
2535 {
2536     KBNODE node;
2537     int selected=0;
2538
2539     for( node = pub_keyblock; node; node = node->next ) {
2540         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2541             selected = node->flag & NODFLG_SELKEY;
2542             if( selected ) {
2543                 delete_kbnode( node );
2544                 if( sec_keyblock ) {
2545                     KBNODE snode;
2546                     int s_selected = 0;
2547                     u32 ki[2];
2548
2549                     keyid_from_pk( node->pkt->pkt.public_key, ki );
2550                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2551                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2552                             u32 ki2[2];
2553
2554                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
2555                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
2556                             if( s_selected )
2557                                 delete_kbnode( snode );
2558                         }
2559                         else if( s_selected
2560                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2561                             delete_kbnode( snode );
2562                         else
2563                             s_selected = 0;
2564                     }
2565                 }
2566             }
2567         }
2568         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2569             delete_kbnode( node );
2570         else
2571             selected = 0;
2572     }
2573     commit_kbnode( &pub_keyblock );
2574     if( sec_keyblock )
2575         commit_kbnode( &sec_keyblock );
2576
2577     /* No need to set update_trust here since signing keys are no
2578        longer used to certify other keys, so there is no change in
2579        trust when revoking/removing them */
2580 }
2581
2582
2583 /****************
2584  * Ask for a new revoker, do the selfsignature and put it into
2585  * both keyblocks.
2586  * Return true if there is a new revoker
2587  */
2588 static int
2589 menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
2590 {
2591   PKT_public_key *pk=NULL,*revoker_pk=NULL;
2592   PKT_secret_key *sk=NULL;
2593   PKT_signature *sig=NULL;
2594   PACKET *pkt;
2595   struct revocation_key revkey;
2596   size_t fprlen;
2597   int rc;
2598
2599   assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
2600   assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
2601
2602   pk=pub_keyblock->pkt->pkt.public_key;
2603
2604   if(pk->numrevkeys==0 && pk->version==3)
2605     {
2606       /* It is legal but bad for compatibility to add a revoker to a
2607          v3 key as it means that PGP2 will not be able to use that key
2608          anymore.  Also, PGP may not expect a revoker on a v3 key.
2609          Don't bother to ask this if the key already has a revoker -
2610          any damage has already been done at that point. -dms */
2611       if(opt.expert)
2612         {
2613           tty_printf(_("WARNING: This is a PGP 2.x-style key.  "
2614                        "Adding a designated revoker may cause\n"
2615                        "         some versions of PGP to reject this key.\n"));
2616
2617           if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay",
2618                                     _("Are you sure you still want "
2619                                       "to add it? (y/N) ")))
2620             return 0;
2621         }
2622       else
2623         {
2624           tty_printf(_("You may not add a designated revoker to "
2625                        "a PGP 2.x-style key.\n"));
2626           return 0;
2627         }
2628     }
2629
2630   sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
2631
2632   for(;;)
2633     {
2634       char *answer;
2635       u32 keyid[2];
2636       char *p;
2637       size_t n;
2638
2639       if(revoker_pk)
2640         free_public_key(revoker_pk);
2641
2642       revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
2643
2644       tty_printf("\n");
2645
2646       answer=cpr_get_utf8("keyedit.add_revoker",
2647                           _("Enter the user ID of the designated revoker: "));
2648       if(answer[0]=='\0' || answer[0]=='\004')
2649         goto fail;
2650
2651       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
2652
2653       if(rc)
2654         {
2655           log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
2656           continue;
2657         }
2658
2659       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
2660       if(fprlen!=20)
2661         {
2662           log_error(_("cannot appoint a PGP 2.x style key as a "
2663                       "designated revoker\n"));
2664           continue;
2665         }
2666
2667       revkey.class=0x80;
2668       if(sensitive)
2669         revkey.class|=0x40;
2670       revkey.algid=revoker_pk->pubkey_algo;
2671
2672       if(cmp_public_keys(revoker_pk,pk)==0)
2673         {
2674           /* This actually causes no harm (after all, a key that
2675              designates itself as a revoker is the same as a
2676              regular key), but it's easy enough to check. */
2677           log_error(_("you cannot appoint a key as its own "
2678                       "designated revoker\n"));
2679
2680           continue;
2681         }
2682
2683       keyid_from_pk(pk,NULL);
2684
2685       /* Does this revkey already exist? */
2686       if(!pk->revkey && pk->numrevkeys)
2687         BUG();
2688       else
2689         {
2690           int i;
2691
2692           for(i=0;i<pk->numrevkeys;i++)
2693             {
2694               if(memcmp(&pk->revkey[i],&revkey,
2695                         sizeof(struct revocation_key))==0)
2696                 {
2697                   char buf[50];
2698
2699                   log_error(_("this key has already been designated "
2700                               "as a revoker\n"));
2701
2702                   sprintf(buf,"%08lX%08lX",
2703                           (ulong)pk->keyid[0],(ulong)pk->keyid[1]);
2704                   write_status_text(STATUS_ALREADY_SIGNED,buf);
2705
2706                   break;
2707                 }
2708             }
2709
2710           if(i<pk->numrevkeys)
2711             continue;
2712         }
2713
2714       keyid_from_pk(revoker_pk,keyid);
2715
2716       tty_printf("\npub   %4u%c/%08lX %s   ",
2717                  nbits_from_pk( revoker_pk ),
2718                  pubkey_letter( revoker_pk->pubkey_algo ),
2719                  (ulong)keyid[1], datestr_from_pk(pk) );
2720
2721       p = get_user_id( keyid, &n );
2722       tty_print_utf8_string( p, n );
2723       m_free(p);
2724       tty_printf("\n");
2725       print_fingerprint(revoker_pk,NULL,2);
2726       tty_printf("\n");
2727
2728       tty_printf(_("WARNING: appointing a key as a designated revoker "
2729                    "cannot be undone!\n"));
2730
2731       tty_printf("\n");
2732
2733       if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
2734                                 _("Are you sure you want to appoint this "
2735                                   "key as a designated revoker? (y/N): ")))
2736         continue;
2737
2738       free_public_key(revoker_pk);
2739       revoker_pk=NULL;
2740       break;
2741     }
2742
2743   /* The 1F signature must be at least v4 to carry the revocation key
2744      subpacket. */
2745   rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0,
2746                            keygen_add_revkey,&revkey );
2747   if( rc )
2748     {
2749       log_error("signing failed: %s\n", g10_errstr(rc) );
2750       goto fail;
2751     }
2752
2753   free_secret_key(sk);
2754   sk=NULL;
2755
2756   /* insert into secret keyblock */
2757   pkt = m_alloc_clear( sizeof *pkt );
2758   pkt->pkttype = PKT_SIGNATURE;
2759   pkt->pkt.signature = copy_signature(NULL, sig);
2760   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2761
2762   /* insert into public keyblock */
2763   pkt = m_alloc_clear( sizeof *pkt );
2764   pkt->pkttype = PKT_SIGNATURE;
2765   pkt->pkt.signature = sig;
2766   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2767
2768   return 1;
2769
2770  fail:
2771   if(sk)
2772     free_secret_key(sk);
2773   if(sig)
2774     free_seckey_enc(sig);
2775   if(revoker_pk)
2776     free_public_key(revoker_pk);
2777
2778   return 0;
2779 }
2780
2781
2782 static int
2783 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
2784 {
2785     int n1, signumber, rc;
2786     u32 expiredate;
2787     int mainkey=0;
2788     PKT_secret_key *sk;    /* copy of the main sk */
2789     PKT_public_key *main_pk, *sub_pk;
2790     PKT_user_id *uid;
2791     KBNODE node;
2792     u32 keyid[2];
2793
2794     if( count_selected_keys( sec_keyblock ) ) {
2795         tty_printf(_("Please remove selections from the secret keys.\n"));
2796         return 0;
2797     }
2798
2799     n1 = count_selected_keys( pub_keyblock );
2800     if( n1 > 1 ) {
2801         tty_printf(_("Please select at most one secondary key.\n"));
2802         return 0;
2803     }
2804     else if( n1 )
2805         tty_printf(_("Changing expiration time for a secondary key.\n"));
2806     else {
2807         tty_printf(_("Changing expiration time for the primary key.\n"));
2808         mainkey=1;
2809     }
2810
2811     no_primary_warning(pub_keyblock,0);
2812
2813     expiredate = ask_expiredate();
2814     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2815     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2816
2817     /* Now we can actually change the self signature(s) */
2818     main_pk = sub_pk = NULL;
2819     uid = NULL;
2820     signumber = 0;
2821     for( node=pub_keyblock; node; node = node->next ) {
2822         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2823             main_pk = node->pkt->pkt.public_key;
2824             keyid_from_pk( main_pk, keyid );
2825             main_pk->expiredate = expiredate;
2826         }
2827         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2828                  && (node->flag & NODFLG_SELKEY ) ) {
2829             sub_pk = node->pkt->pkt.public_key;
2830             sub_pk->expiredate = expiredate;
2831         }
2832         else if( node->pkt->pkttype == PKT_USER_ID )
2833             uid = node->pkt->pkt.user_id;
2834         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
2835                  && ( mainkey || sub_pk ) ) {
2836             PKT_signature *sig = node->pkt->pkt.signature;
2837             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2838                 && ( (mainkey && uid
2839                       && uid->created && (sig->sig_class&~3) == 0x10)
2840                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
2841                 /* this is a selfsignature which is to be replaced */
2842                 PKT_signature *newsig;
2843                 PACKET *newpkt;
2844                 KBNODE sn;
2845                 int signumber2 = 0;
2846
2847                 signumber++;
2848
2849                 if( (mainkey && main_pk->version < 4)
2850                     || (!mainkey && sub_pk->version < 4 ) ) {
2851                     log_info(_(
2852                         "You can't change the expiration date of a v3 key\n"));
2853                     free_secret_key( sk );
2854                     return 0;
2855                 }
2856
2857                 /* find the corresponding secret self-signature */
2858                 for( sn=sec_keyblock; sn; sn = sn->next ) {
2859                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
2860                         PKT_signature *b = sn->pkt->pkt.signature;
2861                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
2862                             && sig->sig_class == b->sig_class
2863                             && ++signumber2 == signumber )
2864                             break;
2865                     }
2866                 }
2867                 if( !sn )
2868                     log_info(_("No corresponding signature in secret ring\n"));
2869
2870                 if( mainkey )
2871                   rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL,
2872                                             sk, keygen_add_key_expire, main_pk);
2873                 else
2874                   rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk,
2875                                             sk, keygen_add_key_expire, sub_pk );
2876                 if( rc ) {
2877                     log_error("make_keysig_packet failed: %s\n",
2878                                                     g10_errstr(rc));
2879                     free_secret_key( sk );
2880                     return 0;
2881                 }
2882                 /* replace the packet */
2883                 newpkt = m_alloc_clear( sizeof *newpkt );
2884                 newpkt->pkttype = PKT_SIGNATURE;
2885                 newpkt->pkt.signature = newsig;
2886                 free_packet( node->pkt );
2887                 m_free( node->pkt );
2888                 node->pkt = newpkt;
2889                 if( sn ) {
2890                     newpkt = m_alloc_clear( sizeof *newpkt );
2891                     newpkt->pkttype = PKT_SIGNATURE;
2892                     newpkt->pkt.signature = copy_signature( NULL, newsig );
2893                     free_packet( sn->pkt );
2894                     m_free( sn->pkt );
2895                     sn->pkt = newpkt;
2896                 }
2897                 sub_pk = NULL;
2898             }
2899         }
2900     }
2901
2902     free_secret_key( sk );
2903     update_trust=1;
2904     return 1;
2905 }
2906
2907 static int
2908 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
2909 {
2910     byte buf[1];
2911
2912     /* first clear all primary uid flags so that we are sure none are
2913      * lingering around */
2914     delete_sig_subpkt (sig->hashed,   SIGSUBPKT_PRIMARY_UID);
2915     delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
2916
2917     /* if opaque is set,we want to set the primary id */
2918     if (opaque) { 
2919         buf[0] = 1;
2920         build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 );
2921     }
2922
2923     return 0;
2924 }
2925
2926
2927 /*
2928  * Set the primary uid flag for the selected UID.  We will also reset
2929  * all other primary uid flags.  For this to work with have to update
2930  * all the signature timestamps.  If we would do this with the current
2931  * time, we lose quite a lot of information, so we use a a kludge to
2932  * do this: Just increment the timestamp by one second which is
2933  * sufficient to updated a signature during import.
2934  */
2935 static int
2936 menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
2937 {
2938     PKT_secret_key *sk;    /* copy of the main sk */
2939     PKT_public_key *main_pk;
2940     PKT_user_id *uid;
2941     KBNODE node;
2942     u32 keyid[2];
2943     int selected;
2944     int attribute = 0;
2945     int modified = 0;
2946
2947     if ( count_selected_uids (pub_keyblock) != 1 ) {
2948         tty_printf(_("Please select exactly one user ID.\n"));
2949         return 0;
2950     }
2951
2952     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2953     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2954
2955     /* Now we can actually change the self signature(s) */
2956     main_pk = NULL;
2957     uid = NULL;
2958     selected = 0;
2959
2960     /* Is our selected uid an attribute packet? */
2961     for ( node=pub_keyblock; node; node = node->next )
2962       if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
2963         attribute = (node->pkt->pkt.user_id->attrib_data!=NULL);
2964
2965     for ( node=pub_keyblock; node; node = node->next ) {
2966         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2967             break; /* ready */
2968
2969         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2970             main_pk = node->pkt->pkt.public_key;
2971             keyid_from_pk( main_pk, keyid );
2972         }
2973         else if ( node->pkt->pkttype == PKT_USER_ID ) {
2974             uid = node->pkt->pkt.user_id;
2975             selected = node->flag & NODFLG_SELUID;
2976         }
2977         else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2978             PKT_signature *sig = node->pkt->pkt.signature;
2979             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2980                 && (uid && (sig->sig_class&~3) == 0x10)
2981                 && attribute == (uid->attrib_data!=NULL)) {
2982               if(sig->version < 4) {
2983                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
2984
2985                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
2986                          user);
2987                 m_free(user);
2988               }
2989               else {
2990                 /* This is a selfsignature which is to be replaced.
2991                    We can just ignore v3 signatures because they are
2992                    not able to carry the primary ID flag.  We also
2993                    ignore self-sigs on user IDs that are not of the
2994                    same type that we are making primary.  That is, if
2995                    we are making a user ID primary, we alter user IDs.
2996                    If we are making an attribute packet primary, we
2997                    alter attribute packets. */
2998
2999                 /* FIXME: We must make sure that we only have one
3000                    self-signature per user ID here (not counting
3001                    revocations) */
3002                 PKT_signature *newsig;
3003                 PACKET *newpkt;
3004                 const byte *p;
3005                 int action;
3006
3007                 /* see whether this signature has the primary UID flag */
3008                 p = parse_sig_subpkt (sig->hashed,
3009                                       SIGSUBPKT_PRIMARY_UID, NULL );
3010                 if ( !p )
3011                     p = parse_sig_subpkt (sig->unhashed,
3012                                           SIGSUBPKT_PRIMARY_UID, NULL );
3013                 if ( p && *p ) /* yes */
3014                     action = selected? 0 : -1;
3015                 else /* no */
3016                     action = selected? 1 : 0;
3017
3018                 if (action) {
3019                     int rc = update_keysig_packet (&newsig, sig,
3020                                                main_pk, uid, NULL,
3021                                                sk,
3022                                                change_primary_uid_cb,
3023                                                action > 0? "x":NULL );
3024                     if( rc ) {
3025                         log_error ("update_keysig_packet failed: %s\n",
3026                                    g10_errstr(rc));
3027                         free_secret_key( sk );
3028                         return 0;
3029                     }
3030                     /* replace the packet */
3031                     newpkt = m_alloc_clear( sizeof *newpkt );
3032                     newpkt->pkttype = PKT_SIGNATURE;
3033                     newpkt->pkt.signature = newsig;
3034                     free_packet( node->pkt );
3035                     m_free( node->pkt );
3036                     node->pkt = newpkt;
3037                     modified = 1;
3038                 }
3039               }
3040             }
3041         }
3042     }
3043
3044     free_secret_key( sk );
3045     return modified;
3046 }
3047
3048
3049 /* 
3050  * Set preferences to new values for the selected user IDs
3051  */
3052 static int
3053 menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
3054 {
3055     PKT_secret_key *sk;    /* copy of the main sk */
3056     PKT_public_key *main_pk;
3057     PKT_user_id *uid;
3058     KBNODE node;
3059     u32 keyid[2];
3060     int selected, select_all;
3061     int modified = 0;
3062
3063     no_primary_warning(pub_keyblock,1);
3064
3065     select_all = !count_selected_uids (pub_keyblock);
3066
3067     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
3068     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
3069
3070     /* Now we can actually change the self signature(s) */
3071     main_pk = NULL;
3072     uid = NULL;
3073     selected = 0;
3074     for ( node=pub_keyblock; node; node = node->next ) {
3075         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
3076             break; /* ready */
3077
3078         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
3079             main_pk = node->pkt->pkt.public_key;
3080             keyid_from_pk( main_pk, keyid );
3081         }
3082         else if ( node->pkt->pkttype == PKT_USER_ID ) {
3083             uid = node->pkt->pkt.user_id;
3084             selected = select_all || (node->flag & NODFLG_SELUID);
3085         }
3086         else if ( main_pk && uid && selected
3087                   && node->pkt->pkttype == PKT_SIGNATURE ) {
3088             PKT_signature *sig = node->pkt->pkt.signature;
3089             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
3090                  && (uid && (sig->sig_class&~3) == 0x10) ) {
3091               if( sig->version < 4 ) {
3092                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
3093
3094                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
3095                          user);
3096                 m_free(user);
3097               }
3098               else {
3099                 /* This is a selfsignature which is to be replaced 
3100                  * We have to ignore v3 signatures because they are
3101                  * not able to carry the preferences */
3102                 PKT_signature *newsig;
3103                 PACKET *newpkt;
3104                 int rc;
3105
3106                 rc = update_keysig_packet (&newsig, sig,
3107                                            main_pk, uid, NULL,
3108                                            sk,
3109                                            keygen_upd_std_prefs,
3110                                            NULL );
3111                 if( rc ) {
3112                     log_error ("update_keysig_packet failed: %s\n",
3113                                g10_errstr(rc));
3114                     free_secret_key( sk );
3115                     return 0;
3116                 }
3117                 /* replace the packet */
3118                 newpkt = m_alloc_clear( sizeof *newpkt );
3119                 newpkt->pkttype = PKT_SIGNATURE;
3120                 newpkt->pkt.signature = newsig;
3121                 free_packet( node->pkt );
3122                 m_free( node->pkt );
3123                 node->pkt = newpkt;
3124                 modified = 1;
3125               }
3126             }
3127         }
3128     }
3129     
3130     free_secret_key( sk );
3131     return modified;
3132 }
3133
3134
3135 /****************
3136  * Select one user id or remove all selection if index is 0.
3137  * Returns: True if the selection changed;
3138  */
3139 static int
3140 menu_select_uid( KBNODE keyblock, int idx )
3141 {
3142     KBNODE node;
3143     int i;
3144
3145     /* first check that the index is valid */
3146     if( idx ) {
3147         for( i=0, node = keyblock; node; node = node->next ) {
3148             if( node->pkt->pkttype == PKT_USER_ID ) {
3149                 if( ++i == idx )
3150                     break;
3151             }
3152         }
3153         if( !node ) {
3154             tty_printf(_("No user ID with index %d\n"), idx );
3155             return 0;
3156         }
3157     }
3158     else { /* reset all */
3159         for( i=0, node = keyblock; node; node = node->next ) {
3160             if( node->pkt->pkttype == PKT_USER_ID )
3161                 node->flag &= ~NODFLG_SELUID;
3162         }
3163         return 1;
3164     }
3165     /* and toggle the new index */
3166     for( i=0, node = keyblock; node; node = node->next ) {
3167         if( node->pkt->pkttype == PKT_USER_ID ) {
3168             if( ++i == idx ) {
3169                 if( (node->flag & NODFLG_SELUID) )
3170                     node->flag &= ~NODFLG_SELUID;
3171                 else
3172                     node->flag |= NODFLG_SELUID;
3173             }
3174         }
3175     }
3176
3177     return 1;
3178 }
3179
3180 /****************
3181  * Select secondary keys
3182  * Returns: True if the selection changed;
3183  */
3184 static int
3185 menu_select_key( KBNODE keyblock, int idx )
3186 {
3187     KBNODE node;
3188     int i;
3189
3190     /* first check that the index is valid */
3191     if( idx ) {
3192         for( i=0, node = keyblock; node; node = node->next ) {
3193             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3194                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
3195                 if( ++i == idx )
3196                     break;
3197             }
3198         }
3199         if( !node ) {
3200             tty_printf(_("No secondary key with index %d\n"), idx );
3201             return 0;
3202         }
3203     }
3204     else { /* reset all */
3205         for( i=0, node = keyblock; node; node = node->next ) {
3206             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3207                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
3208                 node->flag &= ~NODFLG_SELKEY;
3209         }
3210         return 1;
3211     }
3212     /* and set the new index */
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             if( ++i == idx ) {
3217                 if( (node->flag & NODFLG_SELKEY) )
3218                     node->flag &= ~NODFLG_SELKEY;
3219                 else
3220                     node->flag |= NODFLG_SELKEY;
3221             }
3222         }
3223     }
3224
3225     return 1;
3226 }
3227
3228
3229 static int
3230 count_uids_with_flag( KBNODE keyblock, unsigned flag )
3231 {
3232     KBNODE node;
3233     int i=0;
3234
3235     for( node = keyblock; node; node = node->next )
3236         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
3237             i++;
3238     return i;
3239 }
3240
3241 static int
3242 count_keys_with_flag( KBNODE keyblock, unsigned flag )
3243 {
3244     KBNODE node;
3245     int i=0;
3246
3247     for( node = keyblock; node; node = node->next )
3248         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3249               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
3250             && (node->flag & flag) )
3251             i++;
3252     return i;
3253 }
3254
3255 static int
3256 count_uids( KBNODE keyblock )
3257 {
3258     KBNODE node;
3259     int i=0;
3260
3261     for( node = keyblock; node; node = node->next )
3262         if( node->pkt->pkttype == PKT_USER_ID )
3263             i++;
3264     return i;
3265 }
3266
3267
3268 /****************
3269  * Returns true if there is at least one selected user id
3270  */
3271 static int
3272 count_selected_uids( KBNODE keyblock )
3273 {
3274     return count_uids_with_flag( keyblock, NODFLG_SELUID);
3275 }
3276
3277 static int
3278 count_selected_keys( KBNODE keyblock )
3279 {
3280     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
3281 }
3282
3283 /* returns how many real (i.e. not attribute) uids are unmarked */
3284 static int
3285 real_uids_left( KBNODE keyblock )
3286 {
3287   KBNODE node;
3288   int real=0;
3289
3290   for(node=keyblock;node;node=node->next)
3291     if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) &&
3292        !node->pkt->pkt.user_id->attrib_data)
3293       real++;
3294
3295   return real;
3296 }
3297
3298 /*
3299  * Ask whether the signature should be revoked.  If the user commits this,
3300  * flag bit MARK_A is set on the signature and the user ID.
3301  */
3302 static void
3303 ask_revoke_sig( KBNODE keyblock, KBNODE node )
3304 {
3305     int doit=0;
3306     PKT_signature *sig = node->pkt->pkt.signature;
3307     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3308
3309     if( !unode ) {
3310         log_error("Oops: no user ID for signature\n");
3311         return;
3312     }
3313
3314     tty_printf(_("user ID: \""));
3315     tty_print_utf8_string( unode->pkt->pkt.user_id->name,
3316                            unode->pkt->pkt.user_id->len );
3317
3318     if(sig->flags.exportable)
3319       tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
3320                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3321     else
3322       tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"),
3323                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3324
3325     if(sig->flags.expired)
3326       {
3327         tty_printf(_("This signature expired on %s.\n"),
3328                    expirestr_from_sig(sig));
3329         /* Use a different question so we can have different help text */
3330         doit=cpr_get_answer_is_yes("ask_revoke_sig.expired",
3331                         _("Are you sure you still want to revoke it? (y/N) "));
3332       }
3333     else
3334       doit=cpr_get_answer_is_yes("ask_revoke_sig.one",
3335               _("Create a revocation certificate for this signature? (y/N) "));
3336
3337     if(doit) {
3338       node->flag |= NODFLG_MARK_A;
3339       unode->flag |= NODFLG_MARK_A;
3340     }
3341 }
3342
3343 /****************
3344  * Display all user ids of the current public key together with signatures
3345  * done by one of our keys.  Then walk over all this sigs and ask the user
3346  * whether he wants to revoke this signature.
3347  * Return: True when the keyblock has changed.
3348  */
3349 static int
3350 menu_revsig( KBNODE keyblock )
3351 {
3352     PKT_signature *sig;
3353     PKT_public_key *primary_pk;
3354     KBNODE node;
3355     int changed = 0;
3356     int rc, any, skip=1, all=!count_selected_uids(keyblock);
3357     struct revocation_reason_info *reason = NULL;
3358
3359     /* FIXME: detect duplicates here  */
3360     tty_printf(_("You have signed these user IDs:\n"));
3361     for( node = keyblock; node; node = node->next ) {
3362         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
3363         if( node->pkt->pkttype == PKT_USER_ID ) {
3364             if( node->flag&NODFLG_SELUID || all ) {
3365               PKT_user_id *uid = node->pkt->pkt.user_id;
3366               /* Hmmm: Should we show only UIDs with a signature? */
3367               tty_printf("     ");
3368               tty_print_utf8_string( uid->name, uid->len );
3369               tty_printf("\n");
3370               skip=0;
3371             }
3372             else
3373               skip=1;
3374         }
3375         else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
3376                 && ((sig = node->pkt->pkt.signature),
3377                      !seckey_available(sig->keyid)  ) ) {
3378             if( (sig->sig_class&~3) == 0x10 ) {
3379                 tty_printf(_("   signed by %08lX at %s%s%s\n"),
3380                            (ulong)sig->keyid[1], datestr_from_sig(sig),
3381                            sig->flags.exportable?"":" (non-exportable)",
3382                            sig->flags.revocable?"":" (non-revocable)");
3383                 if(sig->flags.revocable)
3384                   node->flag |= NODFLG_SELSIG;
3385             }
3386             else if( sig->sig_class == 0x30 ) {
3387                 tty_printf(_("   revoked by %08lX at %s\n"),
3388                             (ulong)sig->keyid[1], datestr_from_sig(sig) );
3389             }
3390         }
3391     }
3392
3393     /* ask */
3394     for( node = keyblock; node; node = node->next ) {
3395         if( !(node->flag & NODFLG_SELSIG) )
3396             continue;
3397         ask_revoke_sig( keyblock, node );
3398     }
3399
3400     /* present selected */
3401     any = 0;
3402     for( node = keyblock; node; node = node->next ) {
3403         if( !(node->flag & NODFLG_MARK_A) )
3404             continue;
3405         if( !any ) {
3406             any = 1;
3407             tty_printf(_("You are about to revoke these signatures:\n"));
3408         }
3409         if( node->pkt->pkttype == PKT_USER_ID ) {
3410             PKT_user_id *uid = node->pkt->pkt.user_id;
3411             tty_printf("     ");
3412             tty_print_utf8_string( uid->name, uid->len );
3413             tty_printf("\n");
3414         }
3415         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
3416             sig = node->pkt->pkt.signature;
3417             tty_printf(_("   signed by %08lX at %s%s\n"),
3418                        (ulong)sig->keyid[1], datestr_from_sig(sig),
3419                        sig->flags.exportable?"":_(" (non-exportable)") );
3420         }
3421     }
3422     if( !any )
3423         return 0; /* none selected */
3424
3425     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
3426          _("Really create the revocation certificates? (y/N) ")) )
3427         return 0; /* forget it */
3428
3429     reason = ask_revocation_reason( 0, 1, 0 );
3430     if( !reason ) { /* user decided to cancel */
3431         return 0;
3432     }
3433
3434     /* now we can sign the user ids */
3435   reloop: /* (must use this, because we are modifing the list) */
3436     primary_pk = keyblock->pkt->pkt.public_key;
3437     for( node=keyblock; node; node = node->next ) {
3438         KBNODE unode;
3439         PACKET *pkt;
3440         struct sign_attrib attrib;
3441         PKT_secret_key *sk;
3442
3443         if( !(node->flag & NODFLG_MARK_A)
3444             || node->pkt->pkttype != PKT_SIGNATURE )
3445             continue;
3446         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3447         assert( unode ); /* we already checked this */
3448
3449         memset( &attrib, 0, sizeof attrib );
3450         attrib.reason = reason;
3451         attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
3452
3453         node->flag &= ~NODFLG_MARK_A;
3454         sk = m_alloc_secure_clear( sizeof *sk );
3455         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
3456             log_info(_("no secret key\n"));
3457             continue;
3458         }
3459         rc = make_keysig_packet( &sig, primary_pk,
3460                                        unode->pkt->pkt.user_id,
3461                                        NULL,
3462                                        sk,
3463                                        0x30, 0, 0, 0, 0,
3464                                        sign_mk_attrib,
3465                                        &attrib );
3466         free_secret_key(sk);
3467         if( rc ) {
3468             log_error(_("signing failed: %s\n"), g10_errstr(rc));
3469             release_revocation_reason_info( reason );
3470             return changed;
3471         }
3472         changed = 1; /* we changed the keyblock */
3473         update_trust = 1;
3474         /* Are we revoking our own uid? */
3475         if(primary_pk->keyid[0]==sig->keyid[0] &&
3476            primary_pk->keyid[1]==sig->keyid[1])
3477           unode->pkt->pkt.user_id->is_revoked=1;
3478         pkt = m_alloc_clear( sizeof *pkt );
3479         pkt->pkttype = PKT_SIGNATURE;
3480         pkt->pkt.signature = sig;
3481         insert_kbnode( unode, new_kbnode(pkt), 0 );
3482         goto reloop;
3483     }
3484
3485     release_revocation_reason_info( reason );
3486     return changed;
3487 }
3488
3489 /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
3490    keyblock changed. */
3491 static int
3492 menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
3493 {
3494   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
3495   PKT_secret_key *sk = copy_secret_key( NULL,
3496                                         sec_keyblock->pkt->pkt.secret_key );
3497   KBNODE node;
3498   int changed = 0;
3499   int rc;
3500   struct revocation_reason_info *reason = NULL;
3501
3502   /* Note that this is correct as per the RFCs, but nevertheless
3503      somewhat meaningless in the real world.  1991 did define the 0x30
3504      sig class, but PGP 2.x did not actually implement it, so it would
3505      probably be safe to use v4 revocations everywhere. -ds */
3506
3507   for( node = pub_keyblock; node; node = node->next )
3508     if(pk->version>3 || (node->pkt->pkttype==PKT_USER_ID &&
3509                          node->pkt->pkt.user_id->selfsigversion>3))
3510       {
3511         if((reason = ask_revocation_reason( 0, 1, 4 )))
3512           break;
3513         else
3514           goto leave;
3515       }
3516
3517  reloop: /* (better this way because we are modifing the keyring) */
3518   for( node = pub_keyblock; node; node = node->next )
3519     if(node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
3520       {
3521         PKT_user_id *uid=node->pkt->pkt.user_id;
3522
3523         if(uid->is_revoked)
3524           {
3525             char *user=utf8_to_native(uid->name,uid->len,0);
3526             log_info(_("user ID \"%s\" is already revoked\n"),user);
3527             m_free(user);
3528           }
3529         else
3530           {
3531             PACKET *pkt;
3532             PKT_signature *sig;
3533             struct sign_attrib attrib;
3534             u32 timestamp=make_timestamp();
3535
3536             if(uid->created>=timestamp)
3537               {
3538                 /* Okay, this is a problem.  The user ID selfsig was
3539                    created in the future, so we need to warn the user and
3540                    set our revocation timestamp one second after that so
3541                    everything comes out clean. */
3542
3543                 log_info(_("WARNING: a user ID signature is dated %d"
3544                            " seconds in the future\n"),uid->created-timestamp);
3545
3546                 timestamp=uid->created+1;
3547               }
3548
3549             memset( &attrib, 0, sizeof attrib );
3550             attrib.reason = reason;
3551
3552             node->flag &= ~NODFLG_SELUID;
3553
3554             rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x30, 0,
3555                                      (reason==NULL)?3:0, timestamp, 0,
3556                                      sign_mk_attrib, &attrib );
3557             if( rc )
3558               {
3559                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3560                 goto leave;
3561               }
3562             else
3563               {
3564                 pkt = m_alloc_clear( sizeof *pkt );
3565                 pkt->pkttype = PKT_SIGNATURE;
3566                 pkt->pkt.signature = sig;
3567                 insert_kbnode( node, new_kbnode(pkt), 0 );
3568
3569                 /* If the trustdb has an entry for this key+uid then the
3570                    trustdb needs an update. */
3571                 if(!update_trust
3572                    && (get_validity(pk,uid)&TRUST_MASK)>=TRUST_UNDEFINED)
3573                   update_trust=1;
3574
3575                 changed = 1;
3576                 node->pkt->pkt.user_id->is_revoked=1;
3577
3578                 goto reloop;
3579               }
3580           }
3581       }
3582
3583   if(changed)
3584     commit_kbnode( &pub_keyblock );
3585
3586  leave:
3587   free_secret_key(sk);
3588   release_revocation_reason_info( reason );
3589   return changed;
3590 }
3591
3592 /****************
3593  * Revoke some of the secondary keys.
3594  * Hmmm: Should we add a revocation to the secret keyring too?
3595  *       Does its all make sense to duplicate most of the information?
3596  */
3597 static int
3598 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
3599 {
3600     PKT_public_key *mainpk;
3601     KBNODE node;
3602     int changed = 0;
3603     int rc;
3604     struct revocation_reason_info *reason = NULL;
3605
3606     reason = ask_revocation_reason( 1, 0, 0 );
3607     if( !reason ) { /* user decided to cancel */
3608         return 0;
3609     }
3610
3611   reloop: /* (better this way because we are modifing the keyring) */
3612     mainpk = pub_keyblock->pkt->pkt.public_key;
3613     for( node = pub_keyblock; node; node = node->next ) {
3614         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3615             && (node->flag & NODFLG_SELKEY) ) {
3616             PACKET *pkt;
3617             PKT_signature *sig;
3618             PKT_secret_key *sk;
3619             PKT_public_key *subpk = node->pkt->pkt.public_key;
3620             struct sign_attrib attrib;
3621
3622             memset( &attrib, 0, sizeof attrib );
3623             attrib.reason = reason;
3624
3625             node->flag &= ~NODFLG_SELKEY;
3626             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
3627             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk,
3628                                      0x28, 0, 0, 0, 0,
3629                                      sign_mk_attrib, &attrib );
3630             free_secret_key(sk);
3631             if( rc ) {
3632                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3633                 release_revocation_reason_info( reason );
3634                 return changed;
3635             }
3636             changed = 1; /* we changed the keyblock */
3637
3638             pkt = m_alloc_clear( sizeof *pkt );
3639             pkt->pkttype = PKT_SIGNATURE;
3640             pkt->pkt.signature = sig;
3641             insert_kbnode( node, new_kbnode(pkt), 0 );
3642             goto reloop;
3643         }
3644     }
3645     commit_kbnode( &pub_keyblock );
3646     /*commit_kbnode( &sec_keyblock );*/
3647
3648     /* No need to set update_trust here since signing keys no longer
3649        are used to certify other keys, so there is no change in trust
3650        when revoking/removing them */
3651
3652     release_revocation_reason_info( reason );
3653     return changed;
3654 }
3655
3656 /* Note that update_ownertrust is going to mark the trustdb dirty when
3657    enabling or disabling a key.  This is arguably sub-optimal as
3658    disabled keys are still counted in the web of trust, but perhaps
3659    not worth adding extra complexity to change. -ds */
3660 static int
3661 enable_disable_key( KBNODE keyblock, int disable )
3662 {
3663     PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
3664                             ->pkt->pkt.public_key;
3665     unsigned int trust, newtrust;
3666
3667     trust = newtrust = get_ownertrust (pk);
3668     newtrust &= ~TRUST_FLAG_DISABLED;
3669     if( disable )
3670         newtrust |= TRUST_FLAG_DISABLED;
3671     if( trust == newtrust )
3672         return 0; /* already in that state */
3673     update_ownertrust(pk, newtrust );
3674     return 0;
3675 }
3676
3677
3678 static void
3679 menu_showphoto( KBNODE keyblock )
3680 {
3681   KBNODE node;
3682   int select_all = !count_selected_uids(keyblock);
3683   int count=0;
3684   PKT_public_key *pk=NULL;
3685   u32 keyid[2];
3686
3687   /* Look for the public key first.  We have to be really, really,
3688      explicit as to which photo this is, and what key it is a UID on
3689      since people may want to sign it. */
3690
3691   for( node = keyblock; node; node = node->next )
3692     {
3693       if( node->pkt->pkttype == PKT_PUBLIC_KEY )
3694         {
3695           pk = node->pkt->pkt.public_key;
3696           keyid_from_pk(pk, keyid);
3697         }
3698       else if( node->pkt->pkttype == PKT_USER_ID )
3699         {
3700           PKT_user_id *uid = node->pkt->pkt.user_id;
3701           count++;
3702
3703           if((select_all || (node->flag & NODFLG_SELUID)) &&
3704              uid->attribs!=NULL)
3705             {
3706               int i;
3707
3708               for(i=0;i<uid->numattribs;i++)
3709                 {
3710                   byte type;
3711                   u32 size;
3712
3713                   if(uid->attribs[i].type==ATTRIB_IMAGE &&
3714                      parse_image_header(&uid->attribs[i],&type,&size))
3715                     {
3716                       tty_printf(_("Displaying %s photo ID of size %ld for "
3717                                    "key 0x%08lX (uid %d)\n"),
3718                                  image_type_to_string(type,1),
3719                                  (ulong)size,(ulong)keyid[1],count);
3720                       show_photos(&uid->attribs[i],1,pk,NULL);
3721                     }
3722                 }
3723             }
3724         }
3725     }
3726 }