* trustdb.c (validate_keys): Mask the ownertrust when building the list of
[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 ("     ");
1628         tty_printf (_("Cipher: "));
1629         for(i=any=0; prefs[i].type; i++ ) {
1630             if( prefs[i].type == PREFTYPE_SYM ) {
1631                 const char *s = cipher_algo_to_string (prefs[i].value);
1632                 
1633                 if (any)
1634                     tty_printf (", ");
1635                 any = 1;
1636                 /* We don't want to display strings for experimental algos */
1637                 if (s && prefs[i].value < 100 )
1638                     tty_printf ("%s", s );
1639                 else
1640                     tty_printf ("[%d]", prefs[i].value);
1641                 if (prefs[i].value == CIPHER_ALGO_3DES )
1642                     des_seen = 1;
1643             }    
1644         }
1645         if (!des_seen) {
1646             if (any)
1647                 tty_printf (", ");
1648             tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES));
1649         }
1650         tty_printf ("\n     ");
1651         tty_printf (_("Digest: "));
1652         for(i=any=0; prefs[i].type; i++ ) {
1653             if( prefs[i].type == PREFTYPE_HASH ) {
1654                 const char *s = digest_algo_to_string (prefs[i].value);
1655                 
1656                 if (any)
1657                     tty_printf (", ");
1658                 any = 1;
1659                 /* We don't want to display strings for experimental algos */
1660                 if (s && prefs[i].value < 100 )
1661                     tty_printf ("%s", s );
1662                 else
1663                     tty_printf ("[%d]", prefs[i].value);
1664                 if (prefs[i].value == DIGEST_ALGO_SHA1 )
1665                     sha1_seen = 1;
1666             }
1667         }
1668         if (!sha1_seen) {
1669             if (any)
1670                 tty_printf (", ");
1671             tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1));
1672         }
1673         tty_printf ("\n     ");
1674         tty_printf (_("Compression: "));
1675         for(i=any=0; prefs[i].type; i++ ) {
1676             if( prefs[i].type == PREFTYPE_ZIP ) {
1677                 const char *s=compress_algo_to_string(prefs[i].value);
1678                 
1679                 if (any)
1680                     tty_printf (", ");
1681                 any = 1;
1682                 /* We don't want to display strings for experimental algos */
1683                 if (s && prefs[i].value < 100 )
1684                     tty_printf ("%s", s );
1685                 else
1686                     tty_printf ("[%d]", prefs[i].value);
1687                 if (prefs[i].value == 0 )
1688                     uncomp_seen = 1;
1689             }
1690         }
1691         if (!uncomp_seen) {
1692             if (any)
1693                 tty_printf (", ");
1694             else {
1695               tty_printf ("%s",compress_algo_to_string(1));
1696               tty_printf (", ");
1697             }
1698             tty_printf ("%s",compress_algo_to_string(0));
1699         }
1700         if(uid->mdc_feature || !uid->ks_modify)
1701           {
1702             tty_printf ("\n     ");
1703             tty_printf (_("Features: "));
1704             any=0;
1705             if(uid->mdc_feature)
1706               {
1707                 tty_printf ("MDC");
1708                 any=1;
1709               }
1710             if(!uid->ks_modify)
1711               {
1712                 if(any)
1713                   tty_printf (", ");
1714                 tty_printf (_("Keyserver no-modify"));
1715               }
1716           }
1717         tty_printf("\n");
1718     }
1719     else {
1720         tty_printf("    ");
1721         for(i=0; prefs[i].type; i++ ) {
1722             tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM   ? 'S' :
1723                                  prefs[i].type == PREFTYPE_HASH  ? 'H' :
1724                                  prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
1725                                  prefs[i].value);
1726         }
1727         if (uid->mdc_feature)
1728             tty_printf (" [mdc]");
1729         if (!uid->ks_modify)
1730             tty_printf (" [no-ks-modify]");
1731         tty_printf("\n");
1732     }
1733 }
1734
1735
1736 /* This is the version of show_key_with_all_names used when
1737    opt.with_colons is used.  It prints all available data in a easy to
1738    parse format and does not translate utf8 */
1739 static void
1740 show_key_with_all_names_colon (KBNODE keyblock)
1741 {
1742   KBNODE node;
1743   int i, j, ulti_hack=0;
1744   byte pk_version=0;
1745   PKT_public_key *primary=NULL;
1746
1747   /* the keys */
1748   for ( node = keyblock; node; node = node->next )
1749     {
1750       if (node->pkt->pkttype == PKT_PUBLIC_KEY
1751           || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) )
1752         {
1753           PKT_public_key *pk = node->pkt->pkt.public_key;
1754           u32 keyid[2];
1755
1756           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1757             {
1758               pk_version = pk->version;
1759               primary=pk;
1760             }
1761
1762           keyid_from_pk (pk, keyid);
1763
1764           fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout);
1765           if (!pk->is_valid)
1766             putchar ('i');
1767           else if (pk->is_revoked)
1768             putchar ('r');
1769           else if (pk->has_expired)
1770             putchar ('e');
1771           else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks ))
1772             {
1773               int trust = get_validity_info (pk, NULL);
1774               if(trust=='u')
1775                 ulti_hack=1;
1776               putchar (trust);
1777             }
1778
1779           printf (":%u:%d:%08lX%08lX:%lu:%lu:",
1780                   nbits_from_pk (pk),
1781                   pk->pubkey_algo,
1782                   (ulong)keyid[0], (ulong)keyid[1],
1783                   (ulong)pk->timestamp,
1784                   (ulong)pk->expiredate );
1785           if (pk->local_id)
1786             printf ("%lu", pk->local_id);
1787           putchar (':');
1788           if (node->pkt->pkttype==PKT_PUBLIC_KEY
1789               && !(opt.fast_list_mode || opt.no_expensive_trust_checks ))
1790             putchar(get_ownertrust_info (pk));
1791           putchar(':');
1792           putchar('\n');
1793           
1794           print_fingerprint (pk, NULL, 0);
1795
1796           /* print the revoker record */
1797           if( !pk->revkey && pk->numrevkeys )
1798             BUG();
1799           else
1800             {
1801               for (i=0; i < pk->numrevkeys; i++)
1802                 {
1803                   byte *p;
1804
1805                   printf ("rvk:::%d::::::", pk->revkey[i].algid);
1806                   p = pk->revkey[i].fpr;
1807                   for (j=0; j < 20; j++, p++ )
1808                     printf ("%02X", *p);
1809                   printf (":%02x%s:\n", pk->revkey[i].class,
1810                           (pk->revkey[i].class&0x40)?"s":"");
1811                 }
1812             }
1813         }
1814     }
1815   
1816     /* the user ids */
1817     i = 0;
1818     for (node = keyblock; node; node = node->next) 
1819       {
1820         if ( node->pkt->pkttype == PKT_USER_ID )
1821           {
1822             PKT_user_id *uid = node->pkt->pkt.user_id;
1823
1824             ++i;
1825
1826             if(uid->attrib_data)
1827               printf("uat:");
1828             else
1829               printf("uid:");
1830
1831             if ( uid->is_revoked )
1832               printf("r::::::::");
1833             else if ( uid->is_expired )
1834               printf("e::::::::");
1835             else if ( opt.fast_list_mode || opt.no_expensive_trust_checks )
1836               printf("::::::::");
1837             else
1838               {
1839                 int uid_validity;
1840
1841                 if( primary && !ulti_hack )
1842                   uid_validity = get_validity_info( primary, uid );
1843                 else
1844                   uid_validity = 'u';
1845                 printf("%c::::::::",uid_validity);
1846               }
1847
1848             if(uid->attrib_data)
1849               printf ("%u %lu",uid->numattribs,uid->attrib_len);
1850             else
1851               print_string (stdout, uid->name, uid->len, ':');
1852
1853             putchar (':');
1854             /* signature class */
1855             putchar (':');
1856             /* capabilities */
1857             putchar (':');
1858             /* preferences */
1859             if (pk_version>3 || uid->selfsigversion>3)
1860               {
1861                 const prefitem_t *prefs = uid->prefs;
1862                 
1863                 for (j=0; prefs && prefs[j].type; j++)
1864                   {
1865                     if (j)
1866                       putchar (' ');
1867                     printf ("%c%d", prefs[j].type == PREFTYPE_SYM   ? 'S' :
1868                             prefs[j].type == PREFTYPE_HASH  ? 'H' :
1869                             prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
1870                             prefs[j].value);
1871                   } 
1872                 if (uid->mdc_feature)
1873                   printf (",mdc");
1874               } 
1875             putchar (':');
1876             /* flags */
1877             printf ("%d,", i);
1878             if (uid->is_primary)
1879               putchar ('p');
1880             if (uid->is_revoked)
1881               putchar ('r');
1882             if (uid->is_expired)
1883               putchar ('e');
1884             if ((node->flag & NODFLG_SELUID))
1885               putchar ('s');
1886             if ((node->flag & NODFLG_MARK_A))
1887               putchar ('m');
1888             putchar (':');
1889             putchar('\n');
1890           }
1891       }
1892 }
1893
1894
1895 /****************
1896  * Display the key a the user ids, if only_marked is true, do only
1897  * so for user ids with mark A flag set and dont display the index number
1898  */
1899 static void
1900 show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
1901                          int with_fpr, int with_subkeys, int with_prefs )
1902 {
1903     KBNODE node;
1904     int i, rc;
1905     int do_warn = 0;
1906     byte pk_version=0;
1907
1908     if (opt.with_colons)
1909       {
1910         show_key_with_all_names_colon (keyblock);
1911         return;
1912       }
1913
1914     /* the keys */
1915     for( node = keyblock; node; node = node->next ) {
1916         if( node->pkt->pkttype == PKT_PUBLIC_KEY
1917             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
1918             PKT_public_key *pk = node->pkt->pkt.public_key;
1919             const char *otrust="err",*trust="err";
1920
1921             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1922                 /* do it here, so that debug messages don't clutter the
1923                  * output */
1924                 static int did_warn = 0;
1925
1926                 trust = get_validity_string (pk, NULL);
1927                 otrust = get_ownertrust_string (pk);
1928
1929                 /* Show a warning once */
1930                 if (!did_warn
1931                     && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) {
1932                     did_warn = 1;
1933                     do_warn = 1;
1934                 }
1935
1936                 pk_version=pk->version;
1937             }
1938
1939             if(with_revoker) {
1940                 if( !pk->revkey && pk->numrevkeys )
1941                     BUG();
1942                 else
1943                     for(i=0;i<pk->numrevkeys;i++) {
1944                         u32 r_keyid[2];
1945                         char *user;
1946            
1947                         keyid_from_fingerprint(pk->revkey[i].fpr,
1948                                                MAX_FINGERPRINT_LEN,r_keyid);
1949                         
1950                         user=get_user_id_string (r_keyid);
1951                         tty_printf (_("This key may be revoked by %s key "),
1952                                  pubkey_algo_to_string (pk->revkey[i].algid));
1953                         tty_print_utf8_string (user, strlen (user));
1954                         if ((pk->revkey[i].class&0x40))
1955                           tty_printf (_(" (sensitive)"));
1956                         tty_printf ("\n");
1957                         m_free(user);
1958                       }
1959             }
1960
1961             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1962                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
1963                           (node->flag & NODFLG_SELKEY)? '*':' ',
1964                           nbits_from_pk( pk ),
1965                           pubkey_letter( pk->pubkey_algo ),
1966                           (ulong)keyid_from_pk(pk,NULL),
1967                           datestr_from_pk(pk),
1968                           expirestr_from_pk(pk) );
1969             tty_printf("\n");
1970
1971             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1972               {
1973                 tty_printf("                     ");
1974                 tty_printf(_("trust: %-13s"), otrust);
1975                 tty_printf(_("validity: %s"), trust );
1976                 tty_printf("\n");
1977                 if( node->pkt->pkttype == PKT_PUBLIC_KEY
1978                     && (get_ownertrust (pk)&TRUST_FLAG_DISABLED))
1979                   {
1980                     tty_printf("*** ");
1981                     tty_printf(_("This key has been disabled"));
1982                     tty_printf("\n");
1983                   }
1984               }
1985
1986             if( node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr )
1987               {
1988                 print_fingerprint ( pk, NULL, 2 );
1989                 tty_printf("\n");
1990               }
1991         }
1992         else if( node->pkt->pkttype == PKT_SECRET_KEY
1993             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
1994             PKT_secret_key *sk = node->pkt->pkt.secret_key;
1995             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1996                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
1997                           (node->flag & NODFLG_SELKEY)? '*':' ',
1998                           nbits_from_sk( sk ),
1999                           pubkey_letter( sk->pubkey_algo ),
2000                           (ulong)keyid_from_sk(sk,NULL),
2001                           datestr_from_sk(sk),
2002                           expirestr_from_sk(sk) );
2003             tty_printf("\n");
2004         }
2005         else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
2006                  && node->pkt->pkt.signature->sig_class == 0x28       ) {
2007             PKT_signature *sig = node->pkt->pkt.signature;
2008
2009             rc = check_key_signature( keyblock, node, NULL );
2010             if( !rc )
2011                 tty_printf( _("rev! subkey has been revoked: %s\n"),
2012                             datestr_from_sig( sig ) );
2013             else if( rc == G10ERR_BAD_SIGN )
2014                 tty_printf( _("rev- faked revocation found\n") );
2015             else if( rc )
2016                 tty_printf( _("rev? problem checking revocation: %s\n"),
2017                                                          g10_errstr(rc) );
2018         }
2019     }
2020     /* the user ids */
2021     i = 0;
2022     for( node = keyblock; node; node = node->next ) {
2023         if( node->pkt->pkttype == PKT_USER_ID ) {
2024             PKT_user_id *uid = node->pkt->pkt.user_id;
2025             ++i;
2026             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
2027                 if( only_marked )
2028                    tty_printf("     ");
2029                 else if( node->flag & NODFLG_SELUID )
2030                    tty_printf("(%d)* ", i);
2031                 else if( uid->is_primary )
2032                    tty_printf("(%d). ", i);
2033                 else
2034                    tty_printf("(%d)  ", i);
2035                 if ( uid->is_revoked )
2036                     tty_printf ("[revoked] ");
2037                 if ( uid->is_expired )
2038                     tty_printf ("[expired] ");
2039                 tty_print_utf8_string( uid->name, uid->len );
2040                 tty_printf("\n");
2041                 if( with_prefs )
2042                   {
2043                     if(pk_version>3 || uid->selfsigversion>3)
2044                       show_prefs (uid, with_prefs == 2);
2045                     else
2046                       tty_printf(_("There are no preferences on a "
2047                                    "PGP 2.x-style user ID.\n"));
2048                   }
2049             }
2050         }
2051     }
2052
2053     if (do_warn)
2054         tty_printf (_("Please note that the shown key validity "
2055                       "is not necessarily correct\n"
2056                       "unless you restart the program.\n")); 
2057
2058 }
2059
2060
2061 /* Display basic key information.  This fucntion is suitable to show
2062    information on the key without any dependencies on the trustdb or
2063    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
2064    a secret key.*/
2065 void
2066 show_basic_key_info ( KBNODE keyblock )
2067 {
2068   KBNODE node;
2069   int i;
2070
2071   /* The primary key */
2072   for (node = keyblock; node; node = node->next)
2073     {
2074       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
2075         {
2076           PKT_public_key *pk = node->pkt->pkt.public_key;
2077           
2078           /* Note, we use the same format string as in other show
2079              functions to make the translation job easier. */
2080           tty_printf (_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2081                       node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
2082                       ' ',
2083                       nbits_from_pk( pk ),
2084                       pubkey_letter( pk->pubkey_algo ),
2085                       (ulong)keyid_from_pk(pk,NULL),
2086                       datestr_from_pk(pk),
2087                       expirestr_from_pk(pk) );
2088           tty_printf("\n");
2089           print_fingerprint ( pk, NULL, 3 );
2090           tty_printf("\n");
2091         }
2092       else if (node->pkt->pkttype == PKT_SECRET_KEY)
2093         {
2094           PKT_secret_key *sk = node->pkt->pkt.secret_key;
2095           tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
2096                      node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
2097                      ' ',
2098                      nbits_from_sk( sk ),
2099                      pubkey_letter( sk->pubkey_algo ),
2100                      (ulong)keyid_from_sk(sk,NULL),
2101                      datestr_from_sk(sk),
2102                      expirestr_from_sk(sk) );
2103           tty_printf("\n");
2104           print_fingerprint (NULL, sk, 3 );
2105           tty_printf("\n");
2106         }
2107     }
2108
2109   /* The user IDs. */
2110   for (i=0, node = keyblock; node; node = node->next)
2111     {
2112       if (node->pkt->pkttype == PKT_USER_ID)
2113         {
2114           PKT_user_id *uid = node->pkt->pkt.user_id;
2115           ++i;
2116      
2117           tty_printf ("     ");
2118           if (uid->is_revoked)
2119             tty_printf ("[revoked] ");
2120           if ( uid->is_expired )
2121             tty_printf ("[expired] ");
2122           tty_print_utf8_string (uid->name, uid->len);
2123           tty_printf ("\n");
2124         }
2125     }
2126 }
2127
2128 static void
2129 show_key_and_fingerprint( KBNODE keyblock )
2130 {
2131     KBNODE node;
2132     PKT_public_key *pk = NULL;
2133
2134     for( node = keyblock; node; node = node->next ) {
2135         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2136             pk = node->pkt->pkt.public_key;
2137             tty_printf("pub   %4u%c/%08lX %s ",
2138                           nbits_from_pk( pk ),
2139                           pubkey_letter( pk->pubkey_algo ),
2140                           (ulong)keyid_from_pk(pk,NULL),
2141                           datestr_from_pk(pk) );
2142         }
2143         else if( node->pkt->pkttype == PKT_USER_ID ) {
2144             PKT_user_id *uid = node->pkt->pkt.user_id;
2145             tty_print_utf8_string( uid->name, uid->len );
2146             break;
2147         }
2148     }
2149     tty_printf("\n");
2150     if( pk )
2151         print_fingerprint( pk, NULL, 2 );
2152 }
2153
2154
2155
2156 /****************
2157  * Ask for a new user id, do the selfsignature and put it into
2158  * both keyblocks.
2159  * Return true if there is a new user id
2160  */
2161 static int
2162 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
2163 {
2164     PKT_user_id *uid;
2165     PKT_public_key *pk=NULL;
2166     PKT_secret_key *sk=NULL;
2167     PKT_signature *sig=NULL;
2168     PACKET *pkt;
2169     KBNODE node;
2170     KBNODE pub_where=NULL, sec_where=NULL;
2171     int rc;
2172
2173     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
2174         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
2175             pk = node->pkt->pkt.public_key;
2176         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2177             break;
2178     }
2179     if( !node ) /* no subkey */
2180         pub_where = NULL;
2181     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
2182         if( node->pkt->pkttype == PKT_SECRET_KEY )
2183             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2184         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
2185             break;
2186     }
2187     if( !node ) /* no subkey */
2188         sec_where = NULL;
2189     assert(pk && sk);
2190
2191     if(photo) {
2192       int hasattrib=0;
2193
2194       for( node = pub_keyblock; node; node = node->next )
2195         if( node->pkt->pkttype == PKT_USER_ID &&
2196             node->pkt->pkt.user_id->attrib_data!=NULL)
2197           {
2198             hasattrib=1;
2199             break;
2200           }
2201
2202       /* It is legal but bad for compatibility to add a photo ID to a
2203          v3 key as it means that PGP2 will not be able to use that key
2204          anymore.  Also, PGP may not expect a photo on a v3 key.
2205          Don't bother to ask this if the key already has a photo - any
2206          damage has already been done at that point. -dms */
2207       if(pk->version==3 && !hasattrib)
2208         {
2209           if(opt.expert)
2210             {
2211               tty_printf(_("WARNING: This is a PGP2-style key.  "
2212                            "Adding a photo ID may cause some versions\n"
2213                            "         of PGP to reject this key.\n"));
2214
2215               if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay",
2216                                         _("Are you sure you still want "
2217                                           "to add it? (y/N) ")))
2218                 return 0;
2219             }
2220           else
2221             {
2222               tty_printf(_("You may not add a photo ID to "
2223                            "a PGP2-style key.\n"));
2224               return 0;
2225             }
2226         }
2227
2228       uid = generate_photo_id(pk);
2229     } else
2230       uid = generate_user_id();
2231     if( !uid )
2232         return 0;
2233
2234     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
2235                              keygen_add_std_prefs, pk );
2236     free_secret_key( sk );
2237     if( rc ) {
2238         log_error("signing failed: %s\n", g10_errstr(rc) );
2239         free_user_id(uid);
2240         return 0;
2241     }
2242
2243     /* insert/append to secret keyblock */
2244     pkt = m_alloc_clear( sizeof *pkt );
2245     pkt->pkttype = PKT_USER_ID;
2246     pkt->pkt.user_id = scopy_user_id(uid);
2247     node = new_kbnode(pkt);
2248     if( sec_where )
2249         insert_kbnode( sec_where, node, 0 );
2250     else
2251         add_kbnode( sec_keyblock, node );
2252     pkt = m_alloc_clear( sizeof *pkt );
2253     pkt->pkttype = PKT_SIGNATURE;
2254     pkt->pkt.signature = copy_signature(NULL, sig);
2255     if( sec_where )
2256         insert_kbnode( node, new_kbnode(pkt), 0 );
2257     else
2258         add_kbnode( sec_keyblock, new_kbnode(pkt) );
2259     /* insert/append to public keyblock */
2260     pkt = m_alloc_clear( sizeof *pkt );
2261     pkt->pkttype = PKT_USER_ID;
2262     pkt->pkt.user_id = uid;
2263     node = new_kbnode(pkt);
2264     if( pub_where )
2265         insert_kbnode( pub_where, node, 0 );
2266     else
2267         add_kbnode( pub_keyblock, node );
2268     pkt = m_alloc_clear( sizeof *pkt );
2269     pkt->pkttype = PKT_SIGNATURE;
2270     pkt->pkt.signature = copy_signature(NULL, sig);
2271     if( pub_where )
2272         insert_kbnode( node, new_kbnode(pkt), 0 );
2273     else
2274         add_kbnode( pub_keyblock, new_kbnode(pkt) );
2275     return 1;
2276 }
2277
2278
2279 /****************
2280  * Remove all selceted userids from the keyrings
2281  */
2282 static void
2283 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
2284 {
2285     KBNODE node;
2286     int selected=0;
2287
2288     for( node = pub_keyblock; node; node = node->next ) {
2289         if( node->pkt->pkttype == PKT_USER_ID ) {
2290             selected = node->flag & NODFLG_SELUID;
2291             if( selected ) {
2292                 /* Only cause a trust update if we delete a
2293                    non-revoked user id */
2294                 if(!node->pkt->pkt.user_id->is_revoked)
2295                   update_trust=1;
2296                 delete_kbnode( node );
2297                 if( sec_keyblock ) {
2298                     KBNODE snode;
2299                     int s_selected = 0;
2300                     PKT_user_id *uid = node->pkt->pkt.user_id;
2301                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2302                         if( snode->pkt->pkttype == PKT_USER_ID ) {
2303                             PKT_user_id *suid = snode->pkt->pkt.user_id;
2304
2305                             s_selected =
2306                                 (uid->len == suid->len
2307                                  && !memcmp( uid->name, suid->name, uid->len));
2308                             if( s_selected )
2309                                 delete_kbnode( snode );
2310                         }
2311                         else if( s_selected
2312                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2313                             delete_kbnode( snode );
2314                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
2315                             s_selected = 0;
2316                     }
2317                 }
2318             }
2319         }
2320         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2321             delete_kbnode( node );
2322         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2323             selected = 0;
2324     }
2325     commit_kbnode( &pub_keyblock );
2326     if( sec_keyblock )
2327         commit_kbnode( &sec_keyblock );
2328 }
2329
2330
2331 static int
2332 menu_delsig( KBNODE pub_keyblock )
2333 {
2334     KBNODE node;
2335     PKT_user_id *uid = NULL;
2336     int changed=0;
2337
2338     for( node = pub_keyblock; node; node = node->next ) {
2339         if( node->pkt->pkttype == PKT_USER_ID ) {
2340             uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
2341         }
2342         else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2343            int okay, valid, selfsig, inv_sig, no_key, other_err;
2344
2345             tty_printf("uid  ");
2346             tty_print_utf8_string( uid->name, uid->len );
2347             tty_printf("\n");
2348
2349            okay = inv_sig = no_key = other_err = 0;
2350             valid = print_and_check_one_sig( pub_keyblock, node,
2351                                             &inv_sig, &no_key, &other_err,
2352                                             &selfsig, 1 );
2353
2354            if( valid ) {
2355                okay = cpr_get_answer_yes_no_quit(
2356                    "keyedit.delsig.valid",
2357                    _("Delete this good signature? (y/N/q)"));
2358
2359                /* Only update trust if we delete a good signature.
2360                   The other two cases do not affect trust. */
2361                if(okay)
2362                  update_trust=1;
2363            }
2364            else if( inv_sig || other_err )
2365                okay = cpr_get_answer_yes_no_quit(
2366                    "keyedit.delsig.invalid",
2367                    _("Delete this invalid signature? (y/N/q)"));
2368            else if( no_key )
2369                okay = cpr_get_answer_yes_no_quit(
2370                    "keyedit.delsig.unknown",
2371                    _("Delete this unknown signature? (y/N/q)"));
2372
2373             if( okay == -1 )
2374                 break;
2375            if( okay && selfsig && !cpr_get_answer_is_yes(
2376                                "keyedit.delsig.selfsig",
2377                               _("Really delete this self-signature? (y/N)") ))
2378                 okay = 0;
2379             if( okay ) {
2380                 delete_kbnode( node );
2381                 changed++;
2382             }
2383
2384         }
2385         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2386             uid = NULL;
2387     }
2388
2389     if( changed ) {
2390         commit_kbnode( &pub_keyblock );
2391         tty_printf( changed == 1? _("Deleted %d signature.\n")
2392                                 : _("Deleted %d signatures.\n"), changed );
2393     }
2394     else
2395         tty_printf( _("Nothing deleted.\n") );
2396
2397     return changed;
2398 }
2399
2400
2401 /****************
2402  * Remove some of the secondary keys
2403  */
2404 static void
2405 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
2406 {
2407     KBNODE node;
2408     int selected=0;
2409
2410     for( node = pub_keyblock; node; node = node->next ) {
2411         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2412             selected = node->flag & NODFLG_SELKEY;
2413             if( selected ) {
2414                 delete_kbnode( node );
2415                 if( sec_keyblock ) {
2416                     KBNODE snode;
2417                     int s_selected = 0;
2418                     u32 ki[2];
2419
2420                     keyid_from_pk( node->pkt->pkt.public_key, ki );
2421                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2422                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2423                             u32 ki2[2];
2424
2425                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
2426                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
2427                             if( s_selected )
2428                                 delete_kbnode( snode );
2429                         }
2430                         else if( s_selected
2431                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2432                             delete_kbnode( snode );
2433                         else
2434                             s_selected = 0;
2435                     }
2436                 }
2437             }
2438         }
2439         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2440             delete_kbnode( node );
2441         else
2442             selected = 0;
2443     }
2444     commit_kbnode( &pub_keyblock );
2445     if( sec_keyblock )
2446         commit_kbnode( &sec_keyblock );
2447
2448     /* No need to set update_trust here since signing keys no longer
2449        are used to certify other keys, so there is no change in trust
2450        when revoking/removing them */
2451 }
2452
2453
2454 /****************
2455  * Ask for a new revoker, do the selfsignature and put it into
2456  * both keyblocks.
2457  * Return true if there is a new revoker
2458  */
2459 static int
2460 menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
2461 {
2462   PKT_public_key *pk=NULL,*revoker_pk=NULL;
2463   PKT_secret_key *sk=NULL;
2464   PKT_signature *sig=NULL;
2465   PACKET *pkt;
2466   struct revocation_key revkey;
2467   size_t fprlen;
2468   int rc;
2469
2470   assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
2471   assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
2472
2473   pk=pub_keyblock->pkt->pkt.public_key;
2474
2475   if(pk->numrevkeys==0 && pk->version==3)
2476     {
2477       /* It is legal but bad for compatibility to add a revoker to a
2478          v3 key as it means that PGP2 will not be able to use that key
2479          anymore.  Also, PGP may not expect a revoker on a v3 key.
2480          Don't bother to ask this if the key already has a revoker -
2481          any damage has already been done at that point. -dms */
2482       if(opt.expert)
2483         {
2484           tty_printf(_("WARNING: This is a PGP 2.x-style key.  "
2485                        "Adding a designated revoker may cause\n"
2486                        "         some versions of PGP to reject this key.\n"));
2487
2488           if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay",
2489                                     _("Are you sure you still want "
2490                                       "to add it? (y/N) ")))
2491             return 0;
2492         }
2493       else
2494         {
2495           tty_printf(_("You may not add a designated revoker to "
2496                        "a PGP 2.x-style key.\n"));
2497           return 0;
2498         }
2499     }
2500
2501   sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
2502
2503   for(;;)
2504     {
2505       char *answer;
2506       u32 keyid[2];
2507       char *p;
2508       size_t n;
2509
2510       if(revoker_pk)
2511         free_public_key(revoker_pk);
2512
2513       revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
2514
2515       tty_printf("\n");
2516
2517       answer=cpr_get_utf8("keyedit.add_revoker",
2518                           _("Enter the user ID of the designated revoker: "));
2519       if(answer[0]=='\0' || answer[0]=='\004')
2520         goto fail;
2521
2522       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1);
2523
2524       if(rc)
2525         {
2526           log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
2527           continue;
2528         }
2529
2530       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
2531       if(fprlen!=20)
2532         {
2533           log_error(_("cannot appoint a PGP 2.x style key as a "
2534                       "designated revoker\n"));
2535           continue;
2536         }
2537
2538       revkey.class=0x80;
2539       if(sensitive)
2540         revkey.class|=0x40;
2541       revkey.algid=revoker_pk->pubkey_algo;
2542
2543       if(cmp_public_keys(revoker_pk,pk)==0)
2544         {
2545           /* This actually causes no harm (after all, a key that
2546              designates itself as a revoker is the same as a
2547              regular key), but it's easy enough to check. */
2548           log_error(_("you cannot appoint a key as its own "
2549                       "designated revoker\n"));
2550
2551           continue;
2552         }
2553
2554       keyid_from_pk(pk,NULL);
2555
2556       /* Does this revkey already exist? */
2557       if(!pk->revkey && pk->numrevkeys)
2558         BUG();
2559       else
2560         {
2561           int i;
2562
2563           for(i=0;i<pk->numrevkeys;i++)
2564             {
2565               if(memcmp(&pk->revkey[i],&revkey,
2566                         sizeof(struct revocation_key))==0)
2567                 {
2568                   char buf[50];
2569
2570                   log_error(_("this key has already been designated "
2571                               "as a revoker\n"));
2572
2573                   sprintf(buf,"%08lX%08lX",
2574                           (ulong)pk->keyid[0],(ulong)pk->keyid[1]);
2575                   write_status_text(STATUS_ALREADY_SIGNED,buf);
2576
2577                   break;
2578                 }
2579             }
2580
2581           if(i<pk->numrevkeys)
2582             continue;
2583         }
2584
2585       keyid_from_pk(revoker_pk,keyid);
2586
2587       tty_printf("\npub   %4u%c/%08lX %s   ",
2588                  nbits_from_pk( revoker_pk ),
2589                  pubkey_letter( revoker_pk->pubkey_algo ),
2590                  (ulong)keyid[1], datestr_from_pk(pk) );
2591
2592       p = get_user_id( keyid, &n );
2593       tty_print_utf8_string( p, n );
2594       m_free(p);
2595       tty_printf("\n");
2596       print_fingerprint(revoker_pk,NULL,2);
2597       tty_printf("\n");
2598
2599       tty_printf("WARNING: appointing a key as a designated revoker "
2600                  "cannot be undone!\n");
2601
2602       tty_printf("\n");
2603
2604       if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
2605                                 "Are you sure you want to appoint this "
2606                                 "key as a designated revoker? (y/N): "))
2607         continue;
2608
2609       free_public_key(revoker_pk);
2610       revoker_pk=NULL;
2611       break;
2612     }
2613
2614   /* The 1F signature must be at least v4 to carry the revocation key
2615      subpacket. */
2616   rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0,
2617                            keygen_add_revkey,&revkey );
2618   if( rc )
2619     {
2620       log_error("signing failed: %s\n", g10_errstr(rc) );
2621       goto fail;
2622     }
2623
2624   free_secret_key(sk);
2625   sk=NULL;
2626
2627   /* insert into secret keyblock */
2628   pkt = m_alloc_clear( sizeof *pkt );
2629   pkt->pkttype = PKT_SIGNATURE;
2630   pkt->pkt.signature = copy_signature(NULL, sig);
2631   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2632
2633   /* insert into public keyblock */
2634   pkt = m_alloc_clear( sizeof *pkt );
2635   pkt->pkttype = PKT_SIGNATURE;
2636   pkt->pkt.signature = sig;
2637   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2638
2639   return 1;
2640
2641  fail:
2642   if(sk)
2643     free_secret_key(sk);
2644   if(sig)
2645     free_seckey_enc(sig);
2646   if(revoker_pk)
2647     free_public_key(revoker_pk);
2648
2649   return 0;
2650 }
2651
2652
2653 static int
2654 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
2655 {
2656     int n1, signumber, rc;
2657     u32 expiredate;
2658     int mainkey=0;
2659     PKT_secret_key *sk;    /* copy of the main sk */
2660     PKT_public_key *main_pk, *sub_pk;
2661     PKT_user_id *uid;
2662     KBNODE node;
2663     u32 keyid[2];
2664
2665     if( count_selected_keys( sec_keyblock ) ) {
2666         tty_printf(_("Please remove selections from the secret keys.\n"));
2667         return 0;
2668     }
2669
2670     n1 = count_selected_keys( pub_keyblock );
2671     if( n1 > 1 ) {
2672         tty_printf(_("Please select at most one secondary key.\n"));
2673         return 0;
2674     }
2675     else if( n1 )
2676         tty_printf(_("Changing expiration time for a secondary key.\n"));
2677     else {
2678         tty_printf(_("Changing expiration time for the primary key.\n"));
2679         mainkey=1;
2680     }
2681
2682     expiredate = ask_expiredate();
2683     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2684     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2685
2686     /* Now we can actually change the self signature(s) */
2687     main_pk = sub_pk = NULL;
2688     uid = NULL;
2689     signumber = 0;
2690     for( node=pub_keyblock; node; node = node->next ) {
2691         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2692             main_pk = node->pkt->pkt.public_key;
2693             keyid_from_pk( main_pk, keyid );
2694             main_pk->expiredate = expiredate;
2695         }
2696         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2697                  && (node->flag & NODFLG_SELKEY ) ) {
2698             sub_pk = node->pkt->pkt.public_key;
2699             sub_pk->expiredate = expiredate;
2700         }
2701         else if( node->pkt->pkttype == PKT_USER_ID )
2702             uid = node->pkt->pkt.user_id;
2703         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
2704                  && ( mainkey || sub_pk ) ) {
2705             PKT_signature *sig = node->pkt->pkt.signature;
2706             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2707                 && (    (mainkey && uid && (sig->sig_class&~3) == 0x10)
2708                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
2709                 /* this is a selfsignature which is to be replaced */
2710                 PKT_signature *newsig;
2711                 PACKET *newpkt;
2712                 KBNODE sn;
2713                 int signumber2 = 0;
2714
2715                 signumber++;
2716
2717                 if( (mainkey && main_pk->version < 4)
2718                     || (!mainkey && sub_pk->version < 4 ) ) {
2719                     log_info(_(
2720                         "You can't change the expiration date of a v3 key\n"));
2721                     free_secret_key( sk );
2722                     return 0;
2723                 }
2724
2725                 /* find the corresponding secret self-signature */
2726                 for( sn=sec_keyblock; sn; sn = sn->next ) {
2727                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
2728                         PKT_signature *b = sn->pkt->pkt.signature;
2729                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
2730                             && sig->sig_class == b->sig_class
2731                             && ++signumber2 == signumber )
2732                             break;
2733                     }
2734                 }
2735                 if( !sn )
2736                     log_info(_("No corresponding signature in secret ring\n"));
2737
2738                 if( mainkey )
2739                   rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL,
2740                                             sk, keygen_add_key_expire, main_pk);
2741                 else
2742                   rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk,
2743                                             sk, keygen_add_key_expire, sub_pk );
2744                 if( rc ) {
2745                     log_error("make_keysig_packet failed: %s\n",
2746                                                     g10_errstr(rc));
2747                     free_secret_key( sk );
2748                     return 0;
2749                 }
2750                 /* replace the packet */
2751                 newpkt = m_alloc_clear( sizeof *newpkt );
2752                 newpkt->pkttype = PKT_SIGNATURE;
2753                 newpkt->pkt.signature = newsig;
2754                 free_packet( node->pkt );
2755                 m_free( node->pkt );
2756                 node->pkt = newpkt;
2757                 if( sn ) {
2758                     newpkt = m_alloc_clear( sizeof *newpkt );
2759                     newpkt->pkttype = PKT_SIGNATURE;
2760                     newpkt->pkt.signature = copy_signature( NULL, newsig );
2761                     free_packet( sn->pkt );
2762                     m_free( sn->pkt );
2763                     sn->pkt = newpkt;
2764                 }
2765                 sub_pk = NULL;
2766             }
2767         }
2768     }
2769
2770     free_secret_key( sk );
2771     update_trust=1;
2772     return 1;
2773 }
2774
2775 static int
2776 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
2777 {
2778     byte buf[1];
2779
2780     /* first clear all primary uid flags so that we are sure none are
2781      * lingering around */
2782     delete_sig_subpkt (sig->hashed,   SIGSUBPKT_PRIMARY_UID);
2783     delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
2784
2785     /* if opaque is set,we want to set the primary id */
2786     if (opaque) { 
2787         buf[0] = 1;
2788         build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 );
2789     }
2790
2791     return 0;
2792 }
2793
2794
2795 /*
2796  * Set the primary uid flag for the selected UID.  We will also reset
2797  * all other primary uid flags.  For this to work with have to update
2798  * all the signature timestamps.  If we would do this with the current
2799  * time, we lose quite a lot of information, so we use a a kludge to
2800  * do this: Just increment the timestamp by one second which is
2801  * sufficient to updated a signature during import.
2802  */
2803 static int
2804 menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
2805 {
2806     PKT_secret_key *sk;    /* copy of the main sk */
2807     PKT_public_key *main_pk;
2808     PKT_user_id *uid;
2809     KBNODE node;
2810     u32 keyid[2];
2811     int selected;
2812     int attribute = 0;
2813     int modified = 0;
2814
2815     if ( count_selected_uids (pub_keyblock) != 1 ) {
2816         tty_printf(_("Please select exactly one user ID.\n"));
2817         return 0;
2818     }
2819
2820     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2821     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2822
2823     /* Now we can actually change the self signature(s) */
2824     main_pk = NULL;
2825     uid = NULL;
2826     selected = 0;
2827
2828     /* Is our selected uid an attribute packet? */
2829     for ( node=pub_keyblock; node; node = node->next )
2830       if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
2831         attribute = (node->pkt->pkt.user_id->attrib_data!=NULL);
2832
2833     for ( node=pub_keyblock; node; node = node->next ) {
2834         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2835             break; /* ready */
2836
2837         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2838             main_pk = node->pkt->pkt.public_key;
2839             keyid_from_pk( main_pk, keyid );
2840         }
2841         else if ( node->pkt->pkttype == PKT_USER_ID ) {
2842             uid = node->pkt->pkt.user_id;
2843             selected = node->flag & NODFLG_SELUID;
2844         }
2845         else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2846             PKT_signature *sig = node->pkt->pkt.signature;
2847             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2848                 && (uid && (sig->sig_class&~3) == 0x10)
2849                 && attribute == (uid->attrib_data!=NULL)) {
2850               if(sig->version < 4) {
2851                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
2852
2853                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
2854                          user);
2855                 m_free(user);
2856               }
2857               else {
2858                 /* This is a selfsignature which is to be replaced.
2859                    We can just ignore v3 signatures because they are
2860                    not able to carry the primary ID flag.  We also
2861                    ignore self-sigs on user IDs that are not of the
2862                    same type that we are making primary.  That is, if
2863                    we are making a user ID primary, we alter user IDs.
2864                    If we are making an attribute packet primary, we
2865                    alter attribute packets. */
2866
2867                 /* FIXME: We must make sure that we only have one
2868                    self-signature per user ID here (not counting
2869                    revocations) */
2870                 PKT_signature *newsig;
2871                 PACKET *newpkt;
2872                 const byte *p;
2873                 int action;
2874
2875                 /* see whether this signature has the primary UID flag */
2876                 p = parse_sig_subpkt (sig->hashed,
2877                                       SIGSUBPKT_PRIMARY_UID, NULL );
2878                 if ( !p )
2879                     p = parse_sig_subpkt (sig->unhashed,
2880                                           SIGSUBPKT_PRIMARY_UID, NULL );
2881                 if ( p && *p ) /* yes */
2882                     action = selected? 0 : -1;
2883                 else /* no */
2884                     action = selected? 1 : 0;
2885
2886                 if (action) {
2887                     int rc = update_keysig_packet (&newsig, sig,
2888                                                main_pk, uid, NULL,
2889                                                sk,
2890                                                change_primary_uid_cb,
2891                                                action > 0? "x":NULL );
2892                     if( rc ) {
2893                         log_error ("update_keysig_packet failed: %s\n",
2894                                    g10_errstr(rc));
2895                         free_secret_key( sk );
2896                         return 0;
2897                     }
2898                     /* replace the packet */
2899                     newpkt = m_alloc_clear( sizeof *newpkt );
2900                     newpkt->pkttype = PKT_SIGNATURE;
2901                     newpkt->pkt.signature = newsig;
2902                     free_packet( node->pkt );
2903                     m_free( node->pkt );
2904                     node->pkt = newpkt;
2905                     modified = 1;
2906                 }
2907               }
2908             }
2909         }
2910     }
2911
2912     free_secret_key( sk );
2913     return modified;
2914 }
2915
2916
2917 /* 
2918  * Set preferences to new values for the selected user IDs
2919  */
2920 static int
2921 menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
2922 {
2923     PKT_secret_key *sk;    /* copy of the main sk */
2924     PKT_public_key *main_pk;
2925     PKT_user_id *uid;
2926     KBNODE node;
2927     u32 keyid[2];
2928     int selected, select_all;
2929     int modified = 0;
2930
2931     select_all = !count_selected_uids (pub_keyblock);
2932
2933     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2934     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2935
2936     /* Now we can actually change the self signature(s) */
2937     main_pk = NULL;
2938     uid = NULL;
2939     selected = 0;
2940     for ( node=pub_keyblock; node; node = node->next ) {
2941         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2942             break; /* ready */
2943
2944         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2945             main_pk = node->pkt->pkt.public_key;
2946             keyid_from_pk( main_pk, keyid );
2947         }
2948         else if ( node->pkt->pkttype == PKT_USER_ID ) {
2949             uid = node->pkt->pkt.user_id;
2950             selected = select_all || (node->flag & NODFLG_SELUID);
2951         }
2952         else if ( main_pk && uid && selected
2953                   && node->pkt->pkttype == PKT_SIGNATURE ) {
2954             PKT_signature *sig = node->pkt->pkt.signature;
2955             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2956                  && (uid && (sig->sig_class&~3) == 0x10) ) {
2957               if( sig->version < 4 ) {
2958                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
2959
2960                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
2961                          user);
2962                 m_free(user);
2963               }
2964               else {
2965                 /* This is a selfsignature which is to be replaced 
2966                  * We have to ignore v3 signatures because they are
2967                  * not able to carry the preferences */
2968                 PKT_signature *newsig;
2969                 PACKET *newpkt;
2970                 int rc;
2971
2972                 rc = update_keysig_packet (&newsig, sig,
2973                                            main_pk, uid, NULL,
2974                                            sk,
2975                                            keygen_upd_std_prefs,
2976                                            NULL );
2977                 if( rc ) {
2978                     log_error ("update_keysig_packet failed: %s\n",
2979                                g10_errstr(rc));
2980                     free_secret_key( sk );
2981                     return 0;
2982                 }
2983                 /* replace the packet */
2984                 newpkt = m_alloc_clear( sizeof *newpkt );
2985                 newpkt->pkttype = PKT_SIGNATURE;
2986                 newpkt->pkt.signature = newsig;
2987                 free_packet( node->pkt );
2988                 m_free( node->pkt );
2989                 node->pkt = newpkt;
2990                 modified = 1;
2991               }
2992             }
2993         }
2994     }
2995     
2996     free_secret_key( sk );
2997     return modified;
2998 }
2999
3000
3001 /****************
3002  * Select one user id or remove all selection if index is 0.
3003  * Returns: True if the selection changed;
3004  */
3005 static int
3006 menu_select_uid( KBNODE keyblock, int idx )
3007 {
3008     KBNODE node;
3009     int i;
3010
3011     /* first check that the index is valid */
3012     if( idx ) {
3013         for( i=0, node = keyblock; node; node = node->next ) {
3014             if( node->pkt->pkttype == PKT_USER_ID ) {
3015                 if( ++i == idx )
3016                     break;
3017             }
3018         }
3019         if( !node ) {
3020             tty_printf(_("No user ID with index %d\n"), idx );
3021             return 0;
3022         }
3023     }
3024     else { /* reset all */
3025         for( i=0, node = keyblock; node; node = node->next ) {
3026             if( node->pkt->pkttype == PKT_USER_ID )
3027                 node->flag &= ~NODFLG_SELUID;
3028         }
3029         return 1;
3030     }
3031     /* and toggle the new index */
3032     for( i=0, node = keyblock; node; node = node->next ) {
3033         if( node->pkt->pkttype == PKT_USER_ID ) {
3034             if( ++i == idx ) {
3035                 if( (node->flag & NODFLG_SELUID) )
3036                     node->flag &= ~NODFLG_SELUID;
3037                 else
3038                     node->flag |= NODFLG_SELUID;
3039             }
3040         }
3041     }
3042
3043     return 1;
3044 }
3045
3046 /****************
3047  * Select secondary keys
3048  * Returns: True if the selection changed;
3049  */
3050 static int
3051 menu_select_key( KBNODE keyblock, int idx )
3052 {
3053     KBNODE node;
3054     int i;
3055
3056     /* first check that the index is valid */
3057     if( idx ) {
3058         for( i=0, node = keyblock; node; node = node->next ) {
3059             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3060                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
3061                 if( ++i == idx )
3062                     break;
3063             }
3064         }
3065         if( !node ) {
3066             tty_printf(_("No secondary key with index %d\n"), idx );
3067             return 0;
3068         }
3069     }
3070     else { /* reset all */
3071         for( i=0, node = keyblock; node; node = node->next ) {
3072             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3073                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
3074                 node->flag &= ~NODFLG_SELKEY;
3075         }
3076         return 1;
3077     }
3078     /* and set the new index */
3079     for( i=0, node = keyblock; node; node = node->next ) {
3080         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3081             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
3082             if( ++i == idx ) {
3083                 if( (node->flag & NODFLG_SELKEY) )
3084                     node->flag &= ~NODFLG_SELKEY;
3085                 else
3086                     node->flag |= NODFLG_SELKEY;
3087             }
3088         }
3089     }
3090
3091     return 1;
3092 }
3093
3094
3095 static int
3096 count_uids_with_flag( KBNODE keyblock, unsigned flag )
3097 {
3098     KBNODE node;
3099     int i=0;
3100
3101     for( node = keyblock; node; node = node->next )
3102         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
3103             i++;
3104     return i;
3105 }
3106
3107 static int
3108 count_keys_with_flag( KBNODE keyblock, unsigned flag )
3109 {
3110     KBNODE node;
3111     int i=0;
3112
3113     for( node = keyblock; node; node = node->next )
3114         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3115               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
3116             && (node->flag & flag) )
3117             i++;
3118     return i;
3119 }
3120
3121 static int
3122 count_uids( KBNODE keyblock )
3123 {
3124     KBNODE node;
3125     int i=0;
3126
3127     for( node = keyblock; node; node = node->next )
3128         if( node->pkt->pkttype == PKT_USER_ID )
3129             i++;
3130     return i;
3131 }
3132
3133
3134 /****************
3135  * Returns true if there is at least one selected user id
3136  */
3137 static int
3138 count_selected_uids( KBNODE keyblock )
3139 {
3140     return count_uids_with_flag( keyblock, NODFLG_SELUID);
3141 }
3142
3143 static int
3144 count_selected_keys( KBNODE keyblock )
3145 {
3146     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
3147 }
3148
3149 /* returns how many real (i.e. not attribute) uids are unmarked */
3150 static int
3151 real_uids_left( KBNODE keyblock )
3152 {
3153   KBNODE node;
3154   int real=0;
3155
3156   for(node=keyblock;node;node=node->next)
3157     if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) &&
3158        !node->pkt->pkt.user_id->attrib_data)
3159       real++;
3160
3161   return real;
3162 }
3163
3164 /*
3165  * Ask whether the signature should be revoked.  If the user commits this,
3166  * flag bit MARK_A is set on the signature and the user ID.
3167  */
3168 static void
3169 ask_revoke_sig( KBNODE keyblock, KBNODE node )
3170 {
3171     int doit=0;
3172     PKT_signature *sig = node->pkt->pkt.signature;
3173     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3174
3175     if( !unode ) {
3176         log_error("Oops: no user ID for signature\n");
3177         return;
3178     }
3179
3180     tty_printf(_("user ID: \""));
3181     tty_print_utf8_string( unode->pkt->pkt.user_id->name,
3182                            unode->pkt->pkt.user_id->len );
3183
3184     if(sig->flags.exportable)
3185       tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
3186                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3187     else
3188       tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"),
3189                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
3190
3191     if(sig->flags.expired)
3192       {
3193         tty_printf(_("This signature expired on %s.\n"),
3194                    expirestr_from_sig(sig));
3195         /* Use a different question so we can have different help text */
3196         doit=cpr_get_answer_is_yes("ask_revoke_sig.expired",
3197                         _("Are you sure you still want to revoke it? (y/N) "));
3198       }
3199     else
3200       doit=cpr_get_answer_is_yes("ask_revoke_sig.one",
3201               _("Create a revocation certificate for this signature? (y/N) "));
3202
3203     if(doit) {
3204       node->flag |= NODFLG_MARK_A;
3205       unode->flag |= NODFLG_MARK_A;
3206     }
3207 }
3208
3209 /****************
3210  * Display all user ids of the current public key together with signatures
3211  * done by one of our keys.  Then walk over all this sigs and ask the user
3212  * whether he wants to revoke this signature.
3213  * Return: True when the keyblock has changed.
3214  */
3215 static int
3216 menu_revsig( KBNODE keyblock )
3217 {
3218     PKT_signature *sig;
3219     PKT_public_key *primary_pk;
3220     KBNODE node;
3221     int changed = 0;
3222     int rc, any, skip=1, all=!count_selected_uids(keyblock);
3223     struct revocation_reason_info *reason = NULL;
3224
3225     /* FIXME: detect duplicates here  */
3226     tty_printf(_("You have signed these user IDs:\n"));
3227     for( node = keyblock; node; node = node->next ) {
3228         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
3229         if( node->pkt->pkttype == PKT_USER_ID ) {
3230             if( node->flag&NODFLG_SELUID || all ) {
3231               PKT_user_id *uid = node->pkt->pkt.user_id;
3232               /* Hmmm: Should we show only UIDs with a signature? */
3233               tty_printf("     ");
3234               tty_print_utf8_string( uid->name, uid->len );
3235               tty_printf("\n");
3236               skip=0;
3237             }
3238             else
3239               skip=1;
3240         }
3241         else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
3242                 && ((sig = node->pkt->pkt.signature),
3243                      !seckey_available(sig->keyid)  ) ) {
3244             if( (sig->sig_class&~3) == 0x10 ) {
3245                 tty_printf(_("   signed by %08lX at %s%s%s\n"),
3246                            (ulong)sig->keyid[1], datestr_from_sig(sig),
3247                            sig->flags.exportable?"":" (non-exportable)",
3248                            sig->flags.revocable?"":" (non-revocable)");
3249                 if(sig->flags.revocable)
3250                   node->flag |= NODFLG_SELSIG;
3251             }
3252             else if( sig->sig_class == 0x30 ) {
3253                 tty_printf(_("   revoked by %08lX at %s\n"),
3254                             (ulong)sig->keyid[1], datestr_from_sig(sig) );
3255             }
3256         }
3257     }
3258
3259     /* ask */
3260     for( node = keyblock; node; node = node->next ) {
3261         if( !(node->flag & NODFLG_SELSIG) )
3262             continue;
3263         ask_revoke_sig( keyblock, node );
3264     }
3265
3266     /* present selected */
3267     any = 0;
3268     for( node = keyblock; node; node = node->next ) {
3269         if( !(node->flag & NODFLG_MARK_A) )
3270             continue;
3271         if( !any ) {
3272             any = 1;
3273             tty_printf(_("You are about to revoke these signatures:\n"));
3274         }
3275         if( node->pkt->pkttype == PKT_USER_ID ) {
3276             PKT_user_id *uid = node->pkt->pkt.user_id;
3277             tty_printf("     ");
3278             tty_print_utf8_string( uid->name, uid->len );
3279             tty_printf("\n");
3280         }
3281         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
3282             sig = node->pkt->pkt.signature;
3283             tty_printf(_("   signed by %08lX at %s%s\n"),
3284                        (ulong)sig->keyid[1], datestr_from_sig(sig),
3285                        sig->flags.exportable?"":_(" (non-exportable)") );
3286         }
3287     }
3288     if( !any )
3289         return 0; /* none selected */
3290
3291     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
3292          _("Really create the revocation certificates? (y/N) ")) )
3293         return 0; /* forget it */
3294
3295     reason = ask_revocation_reason( 0, 1, 0 );
3296     if( !reason ) { /* user decided to cancel */
3297         return 0;
3298     }
3299
3300     /* now we can sign the user ids */
3301   reloop: /* (must use this, because we are modifing the list) */
3302     primary_pk = keyblock->pkt->pkt.public_key;
3303     for( node=keyblock; node; node = node->next ) {
3304         KBNODE unode;
3305         PACKET *pkt;
3306         struct sign_attrib attrib;
3307         PKT_secret_key *sk;
3308
3309         if( !(node->flag & NODFLG_MARK_A)
3310             || node->pkt->pkttype != PKT_SIGNATURE )
3311             continue;
3312         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3313         assert( unode ); /* we already checked this */
3314
3315         memset( &attrib, 0, sizeof attrib );
3316         attrib.reason = reason;
3317         attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
3318
3319         node->flag &= ~NODFLG_MARK_A;
3320         sk = m_alloc_secure_clear( sizeof *sk );
3321         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
3322             log_info(_("no secret key\n"));
3323             continue;
3324         }
3325         rc = make_keysig_packet( &sig, primary_pk,
3326                                        unode->pkt->pkt.user_id,
3327                                        NULL,
3328                                        sk,
3329                                        0x30, 0, 0, 0, 0,
3330                                        sign_mk_attrib,
3331                                        &attrib );
3332         free_secret_key(sk);
3333         if( rc ) {
3334             log_error(_("signing failed: %s\n"), g10_errstr(rc));
3335             release_revocation_reason_info( reason );
3336             return changed;
3337         }
3338         changed = 1; /* we changed the keyblock */
3339         update_trust = 1;
3340         /* Are we revoking our own uid? */
3341         if(primary_pk->keyid[0]==sig->keyid[0] &&
3342            primary_pk->keyid[1]==sig->keyid[1])
3343           unode->pkt->pkt.user_id->is_revoked=1;
3344         pkt = m_alloc_clear( sizeof *pkt );
3345         pkt->pkttype = PKT_SIGNATURE;
3346         pkt->pkt.signature = sig;
3347         insert_kbnode( unode, new_kbnode(pkt), 0 );
3348         goto reloop;
3349     }
3350
3351     release_revocation_reason_info( reason );
3352     return changed;
3353 }
3354
3355 /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
3356    keyblock changed. */
3357 static int
3358 menu_revuid( KBNODE pub_keyblock, KBNODE sec_keyblock )
3359 {
3360   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
3361   PKT_secret_key *sk = copy_secret_key( NULL,
3362                                         sec_keyblock->pkt->pkt.secret_key );
3363   KBNODE node;
3364   int changed = 0;
3365   int rc;
3366   struct revocation_reason_info *reason = NULL;
3367
3368   /* Note that this is correct as per the RFCs, but nevertheless
3369      somewhat meaningless in the real world.  1991 did define the 0x30
3370      sig class, but PGP 2.x did not actually implement it, so it would
3371      probably be safe to use v4 revocations everywhere. -ds */
3372
3373   for( node = pub_keyblock; node; node = node->next )
3374     if(pk->version>3 || (node->pkt->pkttype==PKT_USER_ID &&
3375                          node->pkt->pkt.user_id->selfsigversion>3))
3376       {
3377         if((reason = ask_revocation_reason( 0, 1, 4 )))
3378           break;
3379         else
3380           goto leave;
3381       }
3382
3383  reloop: /* (better this way because we are modifing the keyring) */
3384   for( node = pub_keyblock; node; node = node->next )
3385     if(node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
3386       {
3387         PKT_user_id *uid=node->pkt->pkt.user_id;
3388
3389         if(uid->is_revoked)
3390           {
3391             char *user=utf8_to_native(uid->name,uid->len,0);
3392             log_info(_("user ID \"%s\" is already revoked\n"),user);
3393             m_free(user);
3394           }
3395         else
3396           {
3397             PACKET *pkt;
3398             PKT_signature *sig;
3399             struct sign_attrib attrib;
3400             u32 timestamp=make_timestamp();
3401
3402             if(uid->created>=timestamp)
3403               {
3404                 /* Okay, this is a problem.  The user ID selfsig was
3405                    created in the future, so we need to warn the user and
3406                    set our revocation timestamp one second after that so
3407                    everything comes out clean. */
3408
3409                 log_info(_("WARNING: a user ID signature is dated %d"
3410                            " seconds in the future\n"),uid->created-timestamp);
3411
3412                 timestamp=uid->created+1;
3413               }
3414
3415             memset( &attrib, 0, sizeof attrib );
3416             attrib.reason = reason;
3417
3418             node->flag &= ~NODFLG_SELUID;
3419
3420             rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x30, 0,
3421                                      (reason==NULL)?3:0, timestamp, 0,
3422                                      sign_mk_attrib, &attrib );
3423             if( rc )
3424               {
3425                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3426                 goto leave;
3427               }
3428             else
3429               {
3430                 pkt = m_alloc_clear( sizeof *pkt );
3431                 pkt->pkttype = PKT_SIGNATURE;
3432                 pkt->pkt.signature = sig;
3433                 insert_kbnode( node, new_kbnode(pkt), 0 );
3434
3435                 /* If the trustdb has an entry for this key+uid then the
3436                    trustdb needs an update. */
3437                 if(!update_trust
3438                    && (get_validity(pk,uid)&TRUST_MASK)>=TRUST_UNDEFINED)
3439                   update_trust=1;
3440
3441                 changed = 1;
3442                 node->pkt->pkt.user_id->is_revoked=1;
3443
3444                 goto reloop;
3445               }
3446           }
3447       }
3448
3449   if(changed)
3450     commit_kbnode( &pub_keyblock );
3451
3452  leave:
3453   free_secret_key(sk);
3454   release_revocation_reason_info( reason );
3455   return changed;
3456 }
3457
3458 /****************
3459  * Revoke some of the secondary keys.
3460  * Hmmm: Should we add a revocation to the secret keyring too?
3461  *       Does its all make sense to duplicate most of the information?
3462  */
3463 static int
3464 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
3465 {
3466     PKT_public_key *mainpk;
3467     KBNODE node;
3468     int changed = 0;
3469     int rc;
3470     struct revocation_reason_info *reason = NULL;
3471
3472     reason = ask_revocation_reason( 1, 0, 0 );
3473     if( !reason ) { /* user decided to cancel */
3474         return 0;
3475     }
3476
3477   reloop: /* (better this way because we are modifing the keyring) */
3478     mainpk = pub_keyblock->pkt->pkt.public_key;
3479     for( node = pub_keyblock; node; node = node->next ) {
3480         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3481             && (node->flag & NODFLG_SELKEY) ) {
3482             PACKET *pkt;
3483             PKT_signature *sig;
3484             PKT_secret_key *sk;
3485             PKT_public_key *subpk = node->pkt->pkt.public_key;
3486             struct sign_attrib attrib;
3487
3488             memset( &attrib, 0, sizeof attrib );
3489             attrib.reason = reason;
3490
3491             node->flag &= ~NODFLG_SELKEY;
3492             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
3493             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk,
3494                                      0x28, 0, 0, 0, 0,
3495                                      sign_mk_attrib, &attrib );
3496             free_secret_key(sk);
3497             if( rc ) {
3498                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3499                 release_revocation_reason_info( reason );
3500                 return changed;
3501             }
3502             changed = 1; /* we changed the keyblock */
3503
3504             pkt = m_alloc_clear( sizeof *pkt );
3505             pkt->pkttype = PKT_SIGNATURE;
3506             pkt->pkt.signature = sig;
3507             insert_kbnode( node, new_kbnode(pkt), 0 );
3508             goto reloop;
3509         }
3510     }
3511     commit_kbnode( &pub_keyblock );
3512     /*commit_kbnode( &sec_keyblock );*/
3513
3514     /* No need to set update_trust here since signing keys no longer
3515        are used to certify other keys, so there is no change in trust
3516        when revoking/removing them */
3517
3518     release_revocation_reason_info( reason );
3519     return changed;
3520 }
3521
3522 /* Note that update_ownertrust is going to mark the trustdb dirty when
3523    enabling or disabling a key.  This is arguably sub-optimal as
3524    disabled keys are still counted in the web of trust, but perhaps
3525    not worth adding extra complexity to change. -ds */
3526 static int
3527 enable_disable_key( KBNODE keyblock, int disable )
3528 {
3529     PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
3530                             ->pkt->pkt.public_key;
3531     unsigned int trust, newtrust;
3532
3533     trust = newtrust = get_ownertrust (pk);
3534     newtrust &= ~TRUST_FLAG_DISABLED;
3535     if( disable )
3536         newtrust |= TRUST_FLAG_DISABLED;
3537     if( trust == newtrust )
3538         return 0; /* already in that state */
3539     update_ownertrust(pk, newtrust );
3540     return 0;
3541 }
3542
3543
3544 static void
3545 menu_showphoto( KBNODE keyblock )
3546 {
3547   KBNODE node;
3548   int select_all = !count_selected_uids(keyblock);
3549   int count=0;
3550   PKT_public_key *pk=NULL;
3551   u32 keyid[2];
3552
3553   /* Look for the public key first.  We have to be really, really,
3554      explicit as to which photo this is, and what key it is a UID on
3555      since people may want to sign it. */
3556
3557   for( node = keyblock; node; node = node->next )
3558     {
3559       if( node->pkt->pkttype == PKT_PUBLIC_KEY )
3560         {
3561           pk = node->pkt->pkt.public_key;
3562           keyid_from_pk(pk, keyid);
3563         }
3564       else if( node->pkt->pkttype == PKT_USER_ID )
3565         {
3566           PKT_user_id *uid = node->pkt->pkt.user_id;
3567           count++;
3568
3569           if((select_all || (node->flag & NODFLG_SELUID)) &&
3570              uid->attribs!=NULL)
3571             {
3572               int i;
3573
3574               for(i=0;i<uid->numattribs;i++)
3575                 {
3576                   byte type;
3577                   u32 size;
3578
3579                   if(uid->attribs[i].type==ATTRIB_IMAGE &&
3580                      parse_image_header(&uid->attribs[i],&type,&size))
3581                     {
3582                       tty_printf(_("Displaying %s photo ID of size %ld for "
3583                                    "key 0x%08lX (uid %d)\n"),
3584                                  image_type_to_string(type,1),
3585                                  (ulong)size,(ulong)keyid[1],count);
3586                       show_photos(&uid->attribs[i],1,pk,NULL);
3587                     }
3588                 }
3589             }
3590         }
3591     }
3592 }