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