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