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