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