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