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