See ChangeLog: Sat Jun 26 12:15:59 CEST 1999 Werner Koch
[gnupg.git] / g10 / keyedit.c
1 /* keyedit.c - keyedit stuff
2  *      Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <ctype.h>
28
29 #include "options.h"
30 #include "packet.h"
31 #include "errors.h"
32 #include "iobuf.h"
33 #include "keydb.h"
34 #include "memory.h"
35 #include "util.h"
36 #include "main.h"
37 #include "trustdb.h"
38 #include "filter.h"
39 #include "ttyio.h"
40 #include "status.h"
41 #include "i18n.h"
42
43 static void show_prefs( KBNODE keyblock, PKT_user_id *uid );
44 static void show_key_with_all_names( KBNODE keyblock,
45             int only_marked, int with_fpr, int with_subkeys, int with_prefs );
46 static void show_key_and_fingerprint( KBNODE keyblock );
47 static void show_fingerprint( PKT_public_key *pk );
48 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
49 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
50 static int  menu_delsig( KBNODE pub_keyblock );
51 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
52 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
53 static int menu_select_uid( KBNODE keyblock, int idx );
54 static int menu_select_key( KBNODE keyblock, int idx );
55 static int count_uids( KBNODE keyblock );
56 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
57 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
58 static int count_selected_uids( KBNODE keyblock );
59 static int count_selected_keys( KBNODE keyblock );
60 static int menu_revsig( KBNODE keyblock );
61 static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
62
63 #define CONTROL_D ('D' - 'A' + 1)
64
65 #define NODFLG_BADSIG (1<<0)  /* bad signature */
66 #define NODFLG_NOKEY  (1<<1)  /* no public key */
67 #define NODFLG_SIGERR (1<<2)  /* other sig error */
68
69 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
70
71 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
72 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
73 #define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
74
75
76 struct sign_uid_attrib {
77     int non_exportable;
78 };
79
80
81
82
83 static int
84 get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
85 {
86     int rc;
87
88     *keyblock = NULL;
89     /* search the userid */
90     rc = find_keyblock_byname( kbpos, username );
91     if( rc ) {
92         log_error(_("%s: user not found\n"), username );
93         return rc;
94     }
95
96     /* read the keyblock */
97     rc = read_keyblock( kbpos, keyblock );
98     if( rc )
99         log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
100     else
101         merge_keys_and_selfsig( *keyblock );
102
103     return rc;
104 }
105
106
107 /****************
108  * Print information about a signature, chek it and return true
109  * if the signature is okay. NODE must be a signature packet.
110  */
111 static int
112 print_and_check_one_sig( KBNODE keyblock, KBNODE node,
113                          int *inv_sigs, int *no_key, int *oth_err,
114                         int *is_selfsig, int print_without_key )
115 {
116     PKT_signature *sig = node->pkt->pkt.signature;
117     int rc, sigrc;
118     int is_rev = sig->sig_class == 0x30;
119
120     switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) {
121       case 0:
122         node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
123         sigrc = '!';
124         break;
125       case G10ERR_BAD_SIGN:
126         node->flag = NODFLG_BADSIG;
127         sigrc = '-';
128         if( inv_sigs )
129             ++*inv_sigs;
130         break;
131       case G10ERR_NO_PUBKEY:
132         node->flag = NODFLG_NOKEY;
133         sigrc = '?';
134         if( no_key )
135             ++*no_key;
136         break;
137       default:
138         node->flag = NODFLG_SIGERR;
139         sigrc = '%';
140         if( oth_err )
141             ++*oth_err;
142         break;
143     }
144     if( sigrc != '?' || print_without_key ) {
145         tty_printf("%s%c       %08lX %s   ",
146                 is_rev? "rev":"sig",
147                 sigrc, sig->keyid[1], datestr_from_sig(sig));
148         if( sigrc == '%' )
149             tty_printf("[%s] ", g10_errstr(rc) );
150         else if( sigrc == '?' )
151             ;
152         else if( *is_selfsig ) {
153             tty_printf( is_rev? _("[revocation]")
154                               : _("[self-signature]") );
155         }
156         else {
157             size_t n;
158             char *p = get_user_id( sig->keyid, &n );
159             tty_print_string( p, n > 40? 40 : n );
160             m_free(p);
161         }
162         tty_printf("\n");
163     }
164     return (sigrc == '!');
165 }
166
167
168
169 /****************
170  * Check the keysigs and set the flags to indicate errors.
171  * Returns true if error found.
172  */
173 static int
174 check_all_keysigs( KBNODE keyblock, int only_selected )
175 {
176     KBNODE kbctx;
177     KBNODE node;
178     int inv_sigs = 0;
179     int no_key = 0;
180     int oth_err = 0;
181     int has_selfsig = 0;
182     int mis_selfsig = 0;
183     int selected = !only_selected;
184     int anyuid = 0;
185
186     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
187         if( node->pkt->pkttype == PKT_USER_ID ) {
188             PKT_user_id *uid = node->pkt->pkt.user_id;
189
190             if( only_selected )
191                 selected = (node->flag & NODFLG_SELUID);
192             if( selected ) {
193                 tty_printf("uid  ");
194                 tty_print_string( uid->name, uid->len );
195                 tty_printf("\n");
196                 if( anyuid && !has_selfsig )
197                     mis_selfsig++;
198                 has_selfsig = 0;
199                 anyuid = 1;
200             }
201         }
202         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
203                  && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
204                      || node->pkt->pkt.signature->sig_class == 0x30 )  ) {
205             int selfsig;
206
207             if( print_and_check_one_sig( keyblock, node, &inv_sigs,
208                                         &no_key, &oth_err, &selfsig, 0 ) ) {
209                 if( selfsig )
210                     has_selfsig = 1;
211             }
212             /* Hmmm: should we update the trustdb here? */
213         }
214     }
215     if( !has_selfsig )
216         mis_selfsig++;
217     if( inv_sigs == 1 )
218         tty_printf(_("1 bad signature\n"), inv_sigs );
219     else if( inv_sigs )
220         tty_printf(_("%d bad signatures\n"), inv_sigs );
221     if( no_key == 1 )
222         tty_printf(_("1 signature not checked due to a missing key\n") );
223     else if( no_key )
224         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
225     if( oth_err == 1 )
226         tty_printf(_("1 signature not checked due to an error\n") );
227     else if( oth_err )
228         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
229     if( mis_selfsig == 1 )
230         tty_printf(_("1 user id without valid self-signature detected\n"));
231     else if( mis_selfsig  )
232         tty_printf(_("%d user ids without valid self-signatures detected\n"),
233                                                                     mis_selfsig);
234
235     return inv_sigs || no_key || oth_err || mis_selfsig;
236 }
237
238
239
240
241 int
242 sign_uid_mk_attrib( PKT_signature *sig, void *opaque )
243 {
244     struct sign_uid_attrib *attrib = opaque;
245     byte buf[8];
246
247     if( attrib->non_exportable ) {
248         buf[0] = 0; /* not exportable */
249         build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
250     }
251
252     return 0;
253 }
254
255
256
257 /****************
258  * Loop over all locusr and and sign the uids after asking.
259  * If no user id is marked, all user ids will be signed;
260  * if some user_ids are marked those will be signed.
261  */
262 static int
263 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
264 {
265     int rc = 0;
266     SK_LIST sk_list = NULL;
267     SK_LIST sk_rover = NULL;
268     PKT_secret_key *sk = NULL;
269     KBNODE node, uidnode;
270     PKT_public_key *primary_pk=NULL;
271     int select_all = !count_selected_uids(keyblock);
272     int upd_trust = 0;
273
274     /* build a list of all signators */
275     rc=build_sk_list( locusr, &sk_list, 0, 1 );
276     if( rc )
277         goto leave;
278
279     /* loop over all signaturs */
280     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
281         u32 sk_keyid[2];
282         size_t n;
283         char *p;
284
285         /* we have to use a copy of the sk, because make_keysig_packet
286          * may remove the protection from sk and if we did other
287          * changes to the secret key, we would save the unprotected
288          * version */
289         if( sk )
290             free_secret_key(sk);
291         sk = copy_secret_key( NULL, sk_rover->sk );
292         keyid_from_sk( sk, sk_keyid );
293         /* set mark A for all selected user ids */
294         for( node=keyblock; node; node = node->next ) {
295             if( select_all || (node->flag & NODFLG_SELUID) )
296                 node->flag |= NODFLG_MARK_A;
297             else
298                 node->flag &= ~NODFLG_MARK_A;
299         }
300         /* reset mark for uids which are already signed */
301         uidnode = NULL;
302         for( node=keyblock; node; node = node->next ) {
303             if( node->pkt->pkttype == PKT_USER_ID ) {
304                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
305             }
306             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
307                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
308                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
309                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
310                     /* Fixme: see whether there is a revocation in which
311                      * case we should allow to sign it again. */
312                     tty_printf(_("Already signed by key %08lX\n"),
313                                                         (ulong)sk_keyid[1] );
314                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
315                 }
316             }
317         }
318         /* check whether any uids are left for signing */
319         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
320             tty_printf(_("Nothing to sign with key %08lX\n"),
321                                                   (ulong)sk_keyid[1] );
322             continue;
323         }
324         /* Ask whether we really should sign these user id(s) */
325         tty_printf("\n");
326         show_key_with_all_names( keyblock, 1, 1, 0, 0 );
327         tty_printf("\n");
328         tty_printf(_(
329              "Are you really sure that you want to sign this key\n"
330              "with your key: \""));
331         p = get_user_id( sk_keyid, &n );
332         tty_print_string( p, n );
333         m_free(p); p = NULL;
334         tty_printf("\"\n\n");
335
336         if( local )
337             tty_printf(
338                   _("The signature will be marked as non-exportable.\n\n"));
339
340
341         if( opt.batch && opt.answer_yes )
342             ;
343         else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
344             continue;
345         /* now we can sign the user ids */
346       reloop: /* (must use this, because we are modifing the list) */
347         primary_pk = NULL;
348         for( node=keyblock; node; node = node->next ) {
349             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
350                 primary_pk = node->pkt->pkt.public_key;
351             else if( node->pkt->pkttype == PKT_USER_ID
352                      && (node->flag & NODFLG_MARK_A) ) {
353                 PACKET *pkt;
354                 PKT_signature *sig;
355                 struct sign_uid_attrib attrib;
356
357                 assert( primary_pk );
358                 memset( &attrib, 0, sizeof attrib );
359                 attrib.non_exportable = local;
360                 node->flag &= ~NODFLG_MARK_A;
361                 rc = make_keysig_packet( &sig, primary_pk,
362                                                node->pkt->pkt.user_id,
363                                                NULL,
364                                                sk,
365                                                0x10, 0,
366                                                sign_uid_mk_attrib,
367                                                &attrib );
368                 if( rc ) {
369                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
370                     goto leave;
371                 }
372                 *ret_modified = 1; /* we changed the keyblock */
373                 upd_trust = 1;
374
375                 pkt = m_alloc_clear( sizeof *pkt );
376                 pkt->pkttype = PKT_SIGNATURE;
377                 pkt->pkt.signature = sig;
378                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
379                 goto reloop;
380             }
381         }
382     } /* end loop over signators */
383     if( upd_trust && primary_pk ) {
384         rc = clear_trust_checked_flag( primary_pk );
385     }
386
387
388   leave:
389     release_sk_list( sk_list );
390     if( sk )
391         free_secret_key(sk);
392     return rc;
393 }
394
395
396
397 /****************
398  * Change the passphrase of the primary and all secondary keys.
399  * We use only one passphrase for all keys.
400  */
401 static int
402 change_passphrase( KBNODE keyblock )
403 {
404     int rc = 0;
405     int changed=0;
406     KBNODE node;
407     PKT_secret_key *sk;
408     char *passphrase = NULL;
409
410     node = find_kbnode( keyblock, PKT_SECRET_KEY );
411     if( !node ) {
412         log_error("Oops; secret key not found anymore!\n");
413         goto leave;
414     }
415     sk = node->pkt->pkt.secret_key;
416
417     switch( is_secret_key_protected( sk ) ) {
418       case -1:
419         rc = G10ERR_PUBKEY_ALGO;
420         break;
421       case 0:
422         tty_printf(_("This key is not protected.\n"));
423         break;
424       default:
425         tty_printf(_("Key is protected.\n"));
426         rc = check_secret_key( sk, 0 );
427         if( !rc )
428             passphrase = get_last_passphrase();
429         break;
430     }
431
432     /* unprotect all subkeys (use the supplied passphrase or ask)*/
433     for(node=keyblock; !rc && node; node = node->next ) {
434         if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
435             PKT_secret_key *subsk = node->pkt->pkt.secret_key;
436             set_next_passphrase( passphrase );
437             rc = check_secret_key( subsk, 0 );
438         }
439     }
440
441     if( rc )
442         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
443     else {
444         DEK *dek = NULL;
445         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
446
447         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
448
449         set_next_passphrase( NULL );
450         for(;;) {
451             s2k->mode = opt.s2k_mode;
452             s2k->hash_algo = opt.s2k_digest_algo;
453             dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
454             if( !dek ) {
455                 tty_printf(_("passphrase not correctly repeated; try again.\n"));
456             }
457             else if( !dek->keylen ) {
458                 rc = 0;
459                 tty_printf(_( "You don't want a passphrase -"
460                             " this is probably a *bad* idea!\n\n"));
461                 if( cpr_get_answer_is_yes("change_passwd.empty.okay",
462                                _("Do you really want to do this? ")))
463                     changed++;
464                 break;
465             }
466             else { /* okay */
467                 sk->protect.algo = dek->algo;
468                 sk->protect.s2k = *s2k;
469                 rc = protect_secret_key( sk, dek );
470                 for(node=keyblock; !rc && node; node = node->next ) {
471                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
472                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
473                         subsk->protect.algo = dek->algo;
474                         subsk->protect.s2k = *s2k;
475                         rc = protect_secret_key( subsk, dek );
476                     }
477                 }
478                 if( rc )
479                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
480                 else
481                     changed++;
482                 break;
483             }
484         }
485         m_free(s2k);
486         m_free(dek);
487     }
488
489   leave:
490     m_free( passphrase );
491     set_next_passphrase( NULL );
492     return changed && !rc;
493 }
494
495
496 /****************
497  * There are some keys out (due to a bug in gnupg), where the sequence
498  * of the packets is wrong.  This function fixes that.
499  * Returns: true if the keyblock has been fixed.
500  *
501  * Note:  This function does not work if there is more than one user ID.
502  */
503 static int
504 fix_keyblock( KBNODE keyblock )
505 {
506     KBNODE node, last, subkey;
507     int fixed=0;
508
509     /* locate key signatures of class 0x10..0x13 behind sub key packets */
510     for( subkey=last=NULL, node = keyblock; node;
511                                             last=node, node = node->next ) {
512         switch( node->pkt->pkttype ) {
513           case PKT_PUBLIC_SUBKEY:
514           case PKT_SECRET_SUBKEY:
515             if( !subkey )
516                 subkey = last; /* actually it is the one before the subkey */
517             break;
518           case PKT_SIGNATURE:
519             if( subkey ) {
520                 PKT_signature *sig = node->pkt->pkt.signature;
521                 if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
522                     log_info(_(
523                         "moving a key signature to the correct place\n"));
524                     last->next = node->next;
525                     node->next = subkey->next;
526                     subkey->next = node;
527                     node = last;
528                     fixed=1;
529                 }
530             }
531             break;
532           default: break;
533         }
534     }
535
536     return fixed;
537 }
538
539 /****************
540  * Menu driven key editor
541  *
542  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
543  */
544
545 void
546 keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
547 {
548     enum cmdids { cmdNONE = 0,
549            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
550            cmdLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG,
551            cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
552            cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
553            cmdNOP };
554     static struct { const char *name;
555                     enum cmdids id;
556                     int need_sk;
557                     const char *desc;
558                   } cmds[] = {
559         { N_("quit")    , cmdQUIT   , 0, N_("quit this menu") },
560         { N_("q")       , cmdQUIT   , 0, NULL   },
561         { N_("save")    , cmdSAVE   , 0, N_("save and quit") },
562         { N_("help")    , cmdHELP   , 0, N_("show this help") },
563         {    "?"        , cmdHELP   , 0, NULL   },
564         { N_("fpr")     , cmdFPR    , 0, N_("show fingerprint") },
565         { N_("list")    , cmdLIST   , 0, N_("list key and user ids") },
566         { N_("l")       , cmdLIST   , 0, NULL   },
567         { N_("uid")     , cmdSELUID , 0, N_("select user id N") },
568         { N_("key")     , cmdSELKEY , 0, N_("select secondary key N") },
569         { N_("check")   , cmdCHECK  , 0, N_("list signatures") },
570         { N_("c")       , cmdCHECK  , 0, NULL },
571         { N_("sign")    , cmdSIGN   , 0, N_("sign the key") },
572         { N_("s")       , cmdSIGN   , 0, NULL },
573         { N_("lsign")   , cmdLSIGN  , 0, N_("sign the key locally") },
574         { N_("debug")   , cmdDEBUG  , 0, NULL },
575         { N_("adduid")  , cmdADDUID , 1, N_("add a user id") },
576         { N_("deluid")  , cmdDELUID , 0, N_("delete user id") },
577         { N_("addkey")  , cmdADDKEY , 1, N_("add a secondary key") },
578         { N_("delkey")  , cmdDELKEY , 0, N_("delete a secondary key") },
579         { N_("delsig")  , cmdDELSIG , 0, N_("delete signatures") },
580         { N_("expire")  , cmdEXPIRE , 1, N_("change the expire date") },
581         { N_("toggle")  , cmdTOGGLE , 1, N_("toggle between secret "
582                                             "and public key listing") },
583         { N_("t"     )  , cmdTOGGLE , 1, NULL },
584         { N_("pref")    , cmdPREF  , 0, N_("list preferences") },
585         { N_("passwd")  , cmdPASSWD , 1, N_("change the passphrase") },
586         { N_("trust")   , cmdTRUST , 0, N_("change the ownertrust") },
587         { N_("revsig")  , cmdREVSIG , 0, N_("revoke signatures") },
588         { N_("revkey")  , cmdREVKEY , 1, N_("revoke a secondary key") },
589
590     { NULL, cmdNONE } };
591     enum cmdids cmd;
592     int rc = 0;
593     KBNODE keyblock = NULL;
594     KBPOS keyblockpos;
595     KBNODE sec_keyblock = NULL;
596     KBPOS sec_keyblockpos;
597     KBNODE cur_keyblock;
598     char *answer = NULL;
599     int redisplay = 1;
600     int modified = 0;
601     int sec_modified = 0;
602     int toggle;
603     int have_commands = !!commands;
604
605
606     if( opt.batch && !have_commands ) {
607         log_error(_("can't do that in batchmode\n"));
608         goto leave;
609     }
610
611     /* first try to locate it as secret key */
612     rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
613     if( !rc ) {
614         rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
615         if( rc ) {
616             log_error("%s: secret keyblock read problem: %s\n",
617                                             username, g10_errstr(rc));
618             goto leave;
619         }
620         merge_keys_and_selfsig( sec_keyblock );
621         if( fix_keyblock( sec_keyblock ) )
622             sec_modified++;
623     }
624
625     /* and now get the public key */
626     rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
627     if( rc )
628         goto leave;
629     if( fix_keyblock( keyblock ) )
630         modified++;
631     if( collapse_uids( &keyblock ) )
632         modified++;
633
634     if( sec_keyblock ) { /* check that they match */
635         /* FIXME: check that they both match */
636         tty_printf(_("Secret key is available.\n"));
637     }
638
639     toggle = 0;
640     cur_keyblock = keyblock;
641     for(;;) { /* main loop */
642         int i, arg_number;
643         char *p;
644
645         tty_printf("\n");
646         if( redisplay ) {
647             show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
648             tty_printf("\n");
649             redisplay = 0;
650         }
651         do {
652             m_free(answer);
653             if( have_commands ) {
654                 if( commands ) {
655                     answer = m_strdup( commands->d );
656                     commands = commands->next;
657                 }
658                 else if( opt.batch ) {
659                     answer = m_strdup("quit");
660                 }
661                 else
662                     have_commands = 0;
663             }
664             if( !have_commands ) {
665                 answer = cpr_get("keyedit.cmd", _("Command> "));
666                 cpr_kill_prompt();
667             }
668             trim_spaces(answer);
669         } while( *answer == '#' );
670
671         arg_number = 0;
672         if( !*answer )
673             cmd = cmdLIST;
674         else if( *answer == CONTROL_D )
675             cmd = cmdQUIT;
676         else if( isdigit( *answer ) ) {
677             cmd = cmdSELUID;
678             arg_number = atoi(answer);
679         }
680         else {
681             if( (p=strchr(answer,' ')) ) {
682                 *p++ = 0;
683                 trim_spaces(answer);
684                 trim_spaces(p);
685                 arg_number = atoi(p);
686             }
687
688             for(i=0; cmds[i].name; i++ )
689                 if( !stricmp( answer, cmds[i].name ) )
690                     break;
691             if( cmds[i].need_sk && !sec_keyblock ) {
692                 tty_printf(_("Need the secret key to do this.\n"));
693                 cmd = cmdNOP;
694             }
695             else
696                 cmd = cmds[i].id;
697         }
698         switch( cmd )  {
699           case cmdHELP:
700             for(i=0; cmds[i].name; i++ ) {
701                 if( cmds[i].need_sk && !sec_keyblock )
702                     ; /* skip if we do not have the secret key */
703                 else if( cmds[i].desc )
704                     tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
705             }
706             break;
707
708           case cmdQUIT:
709             if( have_commands )
710                 goto leave;
711             if( !modified && !sec_modified )
712                 goto leave;
713             if( !cpr_get_answer_is_yes("keyedit.save.okay",
714                                         _("Save changes? ")) ) {
715                 if( cpr_enabled()
716                     || cpr_get_answer_is_yes("keyedit.cancel.okay",
717                                              _("Quit without saving? ")) )
718                     goto leave;
719                 break;
720             }
721             /* fall thru */
722           case cmdSAVE:
723             if( modified || sec_modified  ) {
724                 if( modified ) {
725                     rc = update_keyblock( &keyblockpos, keyblock );
726                     if( rc ) {
727                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
728                         break;
729                     }
730                 }
731                 if( sec_modified ) {
732                     rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
733                     if( rc ) {
734                         log_error(_("update secret failed: %s\n"),
735                                                             g10_errstr(rc) );
736                         break;
737                     }
738                 }
739             }
740             else
741                 tty_printf(_("Key not changed so no update needed.\n"));
742             rc = update_trust_record( keyblock, 0, NULL );
743             if( rc )
744                 log_error(_("update of trustdb failed: %s\n"),
745                             g10_errstr(rc) );
746             goto leave;
747
748           case cmdLIST:
749             redisplay = 1;
750             break;
751
752           case cmdFPR:
753             show_key_and_fingerprint( keyblock );
754             break;
755
756           case cmdSELUID:
757             if( menu_select_uid( cur_keyblock, arg_number ) )
758                 redisplay = 1;
759             break;
760
761           case cmdSELKEY:
762             if( menu_select_key( cur_keyblock, arg_number ) )
763                 redisplay = 1;
764             break;
765
766           case cmdCHECK:
767             /* we can only do this with the public key becuase the
768              * check functions can't cope with secret keys and it
769              * is questionable whether this would make sense at all */
770             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
771             break;
772
773           case cmdSIGN: /* sign (only the public key) */
774           case cmdLSIGN: /* sign (only the public key) */
775             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
776                 if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
777                                            _("Really sign all user ids? ")) ) {
778                     tty_printf(_("Hint: Select the user ids to sign\n"));
779                     break;
780                 }
781             }
782             sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN );
783             break;
784
785           case cmdDEBUG:
786             dump_kbnode( cur_keyblock );
787             break;
788
789           case cmdTOGGLE:
790             toggle = !toggle;
791             cur_keyblock = toggle? sec_keyblock : keyblock;
792             redisplay = 1;
793             break;
794
795           case cmdADDUID:
796             if( menu_adduid( keyblock, sec_keyblock ) ) {
797                 redisplay = 1;
798                 sec_modified = modified = 1;
799                 /* must update the trustdb already here, so that preferences
800                  * get listed correctly */
801                 rc = update_trust_record( keyblock, 0, NULL );
802                 if( rc ) {
803                     log_error(_("update of trustdb failed: %s\n"),
804                                 g10_errstr(rc) );
805                     rc = 0;
806                 }
807             }
808             break;
809
810           case cmdDELUID: {
811                 int n1;
812
813                 if( !(n1=count_selected_uids(keyblock)) )
814                     tty_printf(_("You must select at least one user id.\n"));
815                 else if( count_uids(keyblock) - n1 < 1 )
816                     tty_printf(_("You can't delete the last user id!\n"));
817                 else if( cpr_get_answer_is_yes(
818                             "keyedit.remove.uid.okay",
819                         n1 > 1? _("Really remove all selected user ids? ")
820                               : _("Really remove this user id? ")
821                        ) ) {
822                     menu_deluid( keyblock, sec_keyblock );
823                     redisplay = 1;
824                     modified = 1;
825                     if( sec_keyblock )
826                        sec_modified = 1;
827                 }
828             }
829             break;
830
831           case cmdDELSIG: {
832                 int n1;
833
834                 if( !(n1=count_selected_uids(keyblock)) )
835                     tty_printf(_("You must select at least one user id.\n"));
836                 else if( menu_delsig( keyblock ) ) {
837                     /* no redisplay here, because it may scroll away some
838                      * status output of delsig */
839                     modified = 1;
840                 }
841             }
842             break;
843
844           case cmdADDKEY:
845         secmem_dump_stats();
846             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
847                 redisplay = 1;
848                 sec_modified = modified = 1;
849             }
850         secmem_dump_stats();
851             break;
852
853
854           case cmdDELKEY: {
855                 int n1;
856
857                 if( !(n1=count_selected_keys( keyblock )) )
858                     tty_printf(_("You must select at least one key.\n"));
859                 else if( sec_keyblock && !cpr_get_answer_is_yes(
860                             "keyedit.remove.subkey.okay",
861                        n1 > 1?
862                         _("Do you really want to delete the selected keys? "):
863                         _("Do you really want to delete this key? ")
864                        ))
865                     ;
866                 else {
867                     menu_delkey( keyblock, sec_keyblock );
868                     redisplay = 1;
869                     modified = 1;
870                     if( sec_keyblock )
871                        sec_modified = 1;
872                 }
873             }
874             break;
875
876           case cmdREVKEY: {
877                 int n1;
878
879                 if( !(n1=count_selected_keys( keyblock )) )
880                     tty_printf(_("You must select at least one key.\n"));
881                 else if( sec_keyblock && !cpr_get_answer_is_yes(
882                             "keyedit.revoke.subkey.okay",
883                        n1 > 1?
884                         _("Do you really want to revoke the selected keys? "):
885                         _("Do you really want to revoke this key? ")
886                        ))
887                     ;
888                 else {
889                     if( menu_revkey( keyblock, sec_keyblock ) ) {
890                         modified = 1;
891                         /*sec_modified = 1;*/
892                     }
893                     redisplay = 1;
894                 }
895             }
896             break;
897
898           case cmdEXPIRE:
899             if( menu_expire( keyblock, sec_keyblock ) ) {
900                 merge_keys_and_selfsig( sec_keyblock );
901                 merge_keys_and_selfsig( keyblock );
902                 sec_modified = 1;
903                 modified = 1;
904                 redisplay = 1;
905             }
906             break;
907
908           case cmdPASSWD:
909             if( change_passphrase( sec_keyblock ) )
910                 sec_modified = 1;
911             break;
912
913           case cmdTRUST:
914             show_key_with_all_names( keyblock, 0, 0, 1, 0 );
915             tty_printf("\n");
916             if( edit_ownertrust( find_kbnode( keyblock,
917                       PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
918                 redisplay = 1;
919             /* we don't need to set modified here, as the trustvalues
920              * are updated immediately */
921             break;
922
923           case cmdPREF:
924             show_key_with_all_names( keyblock, 0, 0, 0, 1 );
925             break;
926
927           case cmdNOP:
928             break;
929
930           case cmdREVSIG:
931             if( menu_revsig( keyblock ) ) {
932                 redisplay = 1;
933                 modified = 1;
934             }
935             break;
936
937           default:
938             tty_printf("\n");
939             tty_printf(_("Invalid command  (try \"help\")\n"));
940             break;
941         }
942     } /* end main loop */
943
944   leave:
945     release_kbnode( keyblock );
946     release_kbnode( sec_keyblock );
947     m_free(answer);
948 }
949
950
951 /****************
952  * show preferences of a public keyblock.
953  */
954 static void
955 show_prefs( KBNODE keyblock, PKT_user_id *uid )
956 {
957     KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
958     PKT_public_key *pk;
959     byte *p;
960     int i;
961     size_t n;
962     byte namehash[20];
963
964     if( !node )
965         return; /* is a secret keyblock */
966     pk = node->pkt->pkt.public_key;
967     if( !pk->local_id ) {
968         log_error("oops: no LID\n");
969         return;
970     }
971
972     rmd160_hash_buffer( namehash, uid->name, uid->len );
973
974     p = get_pref_data( pk->local_id, namehash, &n );
975     if( !p )
976         return;
977
978     tty_printf("    ");
979     for(i=0; i < n; i+=2 ) {
980         if( p[i] )
981             tty_printf( " %c%d", p[i] == PREFTYPE_SYM    ? 'S' :
982                                  p[i] == PREFTYPE_HASH   ? 'H' :
983                                  p[i] == PREFTYPE_COMPR  ? 'Z' : '?', p[i+1]);
984     }
985     tty_printf("\n");
986
987     m_free(p);
988 }
989
990
991 /****************
992  * Display the key a the user ids, if only_marked is true, do only
993  * so for user ids with mark A flag set and dont display the index number
994  */
995 static void
996 show_key_with_all_names( KBNODE keyblock, int only_marked,
997                          int with_fpr, int with_subkeys, int with_prefs )
998 {
999     KBNODE node;
1000     int i, rc;
1001
1002     /* the keys */
1003     for( node = keyblock; node; node = node->next ) {
1004         if( node->pkt->pkttype == PKT_PUBLIC_KEY
1005             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
1006             PKT_public_key *pk = node->pkt->pkt.public_key;
1007             int otrust=0, trust=0;
1008
1009             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1010                 /* do it here, so that debug messages don't clutter the
1011                  * output */
1012                 trust = query_trust_info(pk, NULL);
1013                 otrust = get_ownertrust_info( pk->local_id );
1014             }
1015
1016             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s",
1017                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
1018                           (node->flag & NODFLG_SELKEY)? '*':' ',
1019                           nbits_from_pk( pk ),
1020                           pubkey_letter( pk->pubkey_algo ),
1021                           (ulong)keyid_from_pk(pk,NULL),
1022                           datestr_from_pk(pk),
1023                           expirestr_from_pk(pk) );
1024             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1025                 tty_printf(" trust: %c/%c", otrust, trust );
1026                 if( with_fpr  ) {
1027                     tty_printf("\n");
1028                     show_fingerprint( pk );
1029                 }
1030             }
1031             tty_printf("\n");
1032         }
1033         else if( node->pkt->pkttype == PKT_SECRET_KEY
1034             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
1035             PKT_secret_key *sk = node->pkt->pkt.secret_key;
1036             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s\n",
1037                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
1038                           (node->flag & NODFLG_SELKEY)? '*':' ',
1039                           nbits_from_sk( sk ),
1040                           pubkey_letter( sk->pubkey_algo ),
1041                           (ulong)keyid_from_sk(sk,NULL),
1042                           datestr_from_sk(sk),
1043                           expirestr_from_sk(sk) );
1044         }
1045         else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
1046                  && node->pkt->pkt.signature->sig_class == 0x28       ) {
1047             PKT_signature *sig = node->pkt->pkt.signature;
1048
1049             rc = check_key_signature( keyblock, node, NULL );
1050             if( !rc )
1051                 tty_printf( "rev! subkey has been revoked: %s\n",
1052                             datestr_from_sig( sig ) );
1053             else if( rc == G10ERR_BAD_SIGN )
1054                 tty_printf( "rev- faked revocation found\n" );
1055             else if( rc )
1056                 tty_printf( "rev? problem checking revocation: %s\n",
1057                                                          g10_errstr(rc) );
1058         }
1059     }
1060     /* the user ids */
1061     i = 0;
1062     for( node = keyblock; node; node = node->next ) {
1063         if( node->pkt->pkttype == PKT_USER_ID ) {
1064             PKT_user_id *uid = node->pkt->pkt.user_id;
1065             ++i;
1066             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
1067                 if( only_marked )
1068                    tty_printf("     ");
1069                 else if( node->flag & NODFLG_SELUID )
1070                    tty_printf("(%d)* ", i);
1071                 else
1072                    tty_printf("(%d)  ", i);
1073                 tty_print_string( uid->name, uid->len );
1074                 tty_printf("\n");
1075                 if( with_prefs )
1076                     show_prefs( keyblock, uid );
1077             }
1078         }
1079     }
1080 }
1081
1082 static void
1083 show_key_and_fingerprint( KBNODE keyblock )
1084 {
1085     KBNODE node;
1086     PKT_public_key *pk = NULL;
1087
1088     for( node = keyblock; node; node = node->next ) {
1089         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1090             pk = node->pkt->pkt.public_key;
1091             tty_printf("pub  %4u%c/%08lX %s ",
1092                           nbits_from_pk( pk ),
1093                           pubkey_letter( pk->pubkey_algo ),
1094                           (ulong)keyid_from_pk(pk,NULL),
1095                           datestr_from_pk(pk) );
1096         }
1097         else if( node->pkt->pkttype == PKT_USER_ID ) {
1098             PKT_user_id *uid = node->pkt->pkt.user_id;
1099             tty_print_string( uid->name, uid->len );
1100             break;
1101         }
1102     }
1103     tty_printf("\n");
1104     if( pk )
1105         show_fingerprint( pk );
1106 }
1107
1108
1109 static void
1110 show_fingerprint( PKT_public_key *pk )
1111 {
1112     byte array[MAX_FINGERPRINT_LEN], *p;
1113     size_t i, n;
1114
1115     fingerprint_from_pk( pk, array, &n );
1116     p = array;
1117     tty_printf("             Fingerprint:");
1118     if( n == 20 ) {
1119         for(i=0; i < n ; i++, i++, p += 2 ) {
1120             if( i == 10 )
1121                 tty_printf(" ");
1122             tty_printf(" %02X%02X", *p, p[1] );
1123         }
1124     }
1125     else {
1126         for(i=0; i < n ; i++, p++ ) {
1127             if( i && !(i%8) )
1128                 tty_printf(" ");
1129             tty_printf(" %02X", *p );
1130         }
1131     }
1132     tty_printf("\n");
1133 }
1134
1135
1136 /****************
1137  * Ask for a new user id , do the selfsignature and put it into
1138  * both keyblocks.
1139  * Return true if there is a new user id
1140  */
1141 static int
1142 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1143 {
1144     PKT_user_id *uid;
1145     PKT_public_key *pk=NULL;
1146     PKT_secret_key *sk=NULL;
1147     PKT_signature *sig=NULL;
1148     PACKET *pkt;
1149     KBNODE node;
1150     KBNODE pub_where=NULL, sec_where=NULL;
1151     int rc;
1152
1153     uid = generate_user_id();
1154     if( !uid )
1155         return 0;
1156
1157     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1158         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1159             pk = node->pkt->pkt.public_key;
1160         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1161             break;
1162     }
1163     if( !node ) /* no subkey */
1164         pub_where = NULL;
1165     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1166         if( node->pkt->pkttype == PKT_SECRET_KEY )
1167             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1168         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1169             break;
1170     }
1171     if( !node ) /* no subkey */
1172         sec_where = NULL;
1173     assert(pk && sk );
1174
1175     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
1176                              keygen_add_std_prefs, pk );
1177     free_secret_key( sk );
1178     if( rc ) {
1179         log_error("signing failed: %s\n", g10_errstr(rc) );
1180         free_user_id(uid);
1181         return 0;
1182     }
1183
1184     /* insert/append to secret keyblock */
1185     pkt = m_alloc_clear( sizeof *pkt );
1186     pkt->pkttype = PKT_USER_ID;
1187     pkt->pkt.user_id = copy_user_id(NULL, uid);
1188     node = new_kbnode(pkt);
1189     if( sec_where )
1190         insert_kbnode( sec_where, node, 0 );
1191     else
1192         add_kbnode( sec_keyblock, node );
1193     pkt = m_alloc_clear( sizeof *pkt );
1194     pkt->pkttype = PKT_SIGNATURE;
1195     pkt->pkt.signature = copy_signature(NULL, sig);
1196     if( sec_where )
1197         insert_kbnode( node, new_kbnode(pkt), 0 );
1198     else
1199         add_kbnode( sec_keyblock, new_kbnode(pkt) );
1200     /* insert/append to public keyblock */
1201     pkt = m_alloc_clear( sizeof *pkt );
1202     pkt->pkttype = PKT_USER_ID;
1203     pkt->pkt.user_id = uid;
1204     node = new_kbnode(pkt);
1205     if( pub_where )
1206         insert_kbnode( pub_where, node, 0 );
1207     else
1208         add_kbnode( pub_keyblock, node );
1209     pkt = m_alloc_clear( sizeof *pkt );
1210     pkt->pkttype = PKT_SIGNATURE;
1211     pkt->pkt.signature = copy_signature(NULL, sig);
1212     if( pub_where )
1213         insert_kbnode( node, new_kbnode(pkt), 0 );
1214     else
1215         add_kbnode( pub_keyblock, new_kbnode(pkt) );
1216     return 1;
1217 }
1218
1219
1220 /****************
1221  * Remove all selceted userids from the keyrings
1222  */
1223 static void
1224 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1225 {
1226     KBNODE node;
1227     int selected=0;
1228
1229     for( node = pub_keyblock; node; node = node->next ) {
1230         if( node->pkt->pkttype == PKT_USER_ID ) {
1231             selected = node->flag & NODFLG_SELUID;
1232             if( selected ) {
1233                 delete_kbnode( node );
1234                 if( sec_keyblock ) {
1235                     KBNODE snode;
1236                     int s_selected = 0;
1237                     PKT_user_id *uid = node->pkt->pkt.user_id;
1238                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1239                         if( snode->pkt->pkttype == PKT_USER_ID ) {
1240                             PKT_user_id *suid = snode->pkt->pkt.user_id;
1241
1242                             s_selected =
1243                                 (uid->len == suid->len
1244                                  && !memcmp( uid->name, suid->name, uid->len));
1245                             if( s_selected )
1246                                 delete_kbnode( snode );
1247                         }
1248                         else if( s_selected
1249                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1250                             delete_kbnode( snode );
1251                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1252                             s_selected = 0;
1253                     }
1254                 }
1255             }
1256         }
1257         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1258             delete_kbnode( node );
1259         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1260             selected = 0;
1261     }
1262     commit_kbnode( &pub_keyblock );
1263     if( sec_keyblock )
1264         commit_kbnode( &sec_keyblock );
1265 }
1266
1267
1268 static int
1269 menu_delsig( KBNODE pub_keyblock )
1270 {
1271     KBNODE node;
1272     PKT_user_id *uid = NULL;
1273     int changed=0;
1274
1275     for( node = pub_keyblock; node; node = node->next ) {
1276         if( node->pkt->pkttype == PKT_USER_ID ) {
1277             uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
1278         }
1279         else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
1280            int okay, valid, selfsig, inv_sig, no_key, other_err;
1281
1282             tty_printf("uid  ");
1283             tty_print_string( uid->name, uid->len );
1284             tty_printf("\n");
1285
1286            okay = inv_sig = no_key = other_err = 0;
1287             valid = print_and_check_one_sig( pub_keyblock, node,
1288                                             &inv_sig, &no_key, &other_err,
1289                                             &selfsig, 1 );
1290
1291            if( valid )
1292                okay = cpr_get_answer_yes_no_quit(
1293                    "keyedit.delsig.valid",
1294                    _("Delete this good signature? (y/N/q)"));
1295            else if( inv_sig || other_err )
1296                okay = cpr_get_answer_yes_no_quit(
1297                    "keyedit.delsig.invalid",
1298                    _("Delete this invalid signature? (y/N/q)"));
1299            else if( no_key )
1300                okay = cpr_get_answer_yes_no_quit(
1301                    "keyedit.delsig.unknown",
1302                    _("Delete this unknown signature? (y/N/q)"));
1303
1304             if( okay == -1 )
1305                 break;
1306            if( okay && selfsig && !cpr_get_answer_is_yes(
1307                                "keyedit.delsig.selfsig",
1308                               _("Really delete this self-signature? (y/N)") ))
1309                 okay = 0;
1310             if( okay ) {
1311                 delete_kbnode( node );
1312                 changed++;
1313             }
1314
1315         }
1316         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1317             uid = NULL;
1318     }
1319
1320     if( changed ) {
1321         commit_kbnode( &pub_keyblock );
1322         tty_printf( changed == 1? _("Deleted %d signature.\n")
1323                                 : _("Deleted %d signatures.\n"), changed );
1324     }
1325     else
1326         tty_printf( _("Nothing deleted.\n") );
1327
1328     return changed;
1329 }
1330
1331
1332 /****************
1333  * Remove some of the secondary keys
1334  */
1335 static void
1336 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1337 {
1338     KBNODE node;
1339     int selected=0;
1340
1341     for( node = pub_keyblock; node; node = node->next ) {
1342         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1343             selected = node->flag & NODFLG_SELKEY;
1344             if( selected ) {
1345                 delete_kbnode( node );
1346                 if( sec_keyblock ) {
1347                     KBNODE snode;
1348                     int s_selected = 0;
1349                     u32 ki[2];
1350
1351                     keyid_from_pk( node->pkt->pkt.public_key, ki );
1352                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1353                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1354                             u32 ki2[2];
1355
1356                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1357                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1358                             if( s_selected )
1359                                 delete_kbnode( snode );
1360                         }
1361                         else if( s_selected
1362                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1363                             delete_kbnode( snode );
1364                         else
1365                             s_selected = 0;
1366                     }
1367                 }
1368             }
1369         }
1370         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1371             delete_kbnode( node );
1372         else
1373             selected = 0;
1374     }
1375     commit_kbnode( &pub_keyblock );
1376     if( sec_keyblock )
1377         commit_kbnode( &sec_keyblock );
1378 }
1379
1380
1381
1382 static int
1383 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
1384 {
1385     int n1, signumber, rc;
1386     u32 expiredate;
1387     int mainkey=0;
1388     PKT_secret_key *sk;    /* copy of the main sk */
1389     PKT_public_key *main_pk, *sub_pk;
1390     PKT_user_id *uid;
1391     KBNODE node;
1392     u32 keyid[2];
1393
1394     if( count_selected_keys( sec_keyblock ) ) {
1395         tty_printf(_("Please remove selections from the secret keys.\n"));
1396         return 0;
1397     }
1398
1399     n1 = count_selected_keys( pub_keyblock );
1400     if( n1 > 1 ) {
1401         tty_printf(_("Please select at most one secondary key.\n"));
1402         return 0;
1403     }
1404     else if( n1 )
1405         tty_printf(_("Changing expiration time for a secondary key.\n"));
1406     else {
1407         tty_printf(_("Changing expiration time for the primary key.\n"));
1408         mainkey=1;
1409     }
1410
1411     expiredate = ask_expiredate();
1412     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
1413     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1414
1415     /* Now we can actually change the self signature(s) */
1416     main_pk = sub_pk = NULL;
1417     uid = NULL;
1418     signumber = 0;
1419     for( node=pub_keyblock; node; node = node->next ) {
1420         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1421             main_pk = node->pkt->pkt.public_key;
1422             keyid_from_pk( main_pk, keyid );
1423             main_pk->expiredate = expiredate;
1424         }
1425         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1426                  && (node->flag & NODFLG_SELKEY ) ) {
1427             sub_pk = node->pkt->pkt.public_key;
1428             sub_pk->expiredate = expiredate;
1429         }
1430         else if( node->pkt->pkttype == PKT_USER_ID )
1431             uid = node->pkt->pkt.user_id;
1432         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
1433             PKT_signature *sig = node->pkt->pkt.signature;
1434             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
1435                 && (    (mainkey && uid && (sig->sig_class&~3) == 0x10)
1436                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
1437                 /* this is a selfsignature which is to be replaced */
1438                 PKT_signature *newsig;
1439                 PACKET *newpkt;
1440                 KBNODE sn;
1441                 int signumber2 = 0;
1442
1443                 signumber++;
1444
1445                 if( (mainkey && main_pk->version < 4)
1446                     || (!mainkey && sub_pk->version < 4 ) ) {
1447                     log_info(_(
1448                         "You can't change the expiration date of a v3 key\n"));
1449                     free_secret_key( sk );
1450                     return 0;
1451                 }
1452
1453                 /* find the corresponding secret self-signature */
1454                 for( sn=sec_keyblock; sn; sn = sn->next ) {
1455                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
1456                         PKT_signature *b = sn->pkt->pkt.signature;
1457                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
1458                             && sig->sig_class == b->sig_class
1459                             && ++signumber2 == signumber )
1460                             break;
1461                     }
1462                 }
1463                 if( !sn )
1464                     log_info(_("No corresponding signature in secret ring\n"));
1465
1466                 /* create new self signature */
1467                 if( mainkey )
1468                     rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
1469                                              sk, 0x13, 0,
1470                                              keygen_add_std_prefs, main_pk );
1471                 else
1472                     rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
1473                                              sk, 0x18, 0,
1474                                              keygen_add_key_expire, sub_pk );
1475                 if( rc ) {
1476                     log_error("make_keysig_packet failed: %s\n",
1477                                                     g10_errstr(rc));
1478                     free_secret_key( sk );
1479                     return 0;
1480                 }
1481                 /* replace the packet */
1482                 newpkt = m_alloc_clear( sizeof *newpkt );
1483                 newpkt->pkttype = PKT_SIGNATURE;
1484                 newpkt->pkt.signature = newsig;
1485                 free_packet( node->pkt );
1486                 m_free( node->pkt );
1487                 node->pkt = newpkt;
1488                 if( sn ) {
1489                     newpkt = m_alloc_clear( sizeof *newpkt );
1490                     newpkt->pkttype = PKT_SIGNATURE;
1491                     newpkt->pkt.signature = copy_signature( NULL, newsig );
1492                     free_packet( sn->pkt );
1493                     m_free( sn->pkt );
1494                     sn->pkt = newpkt;
1495                 }
1496             }
1497         }
1498     }
1499
1500     free_secret_key( sk );
1501     return 1;
1502 }
1503
1504
1505 /****************
1506  * Select one user id or remove all selection if index is 0.
1507  * Returns: True if the selection changed;
1508  */
1509 static int
1510 menu_select_uid( KBNODE keyblock, int idx )
1511 {
1512     KBNODE node;
1513     int i;
1514
1515     /* first check that the index is valid */
1516     if( idx ) {
1517         for( i=0, node = keyblock; node; node = node->next ) {
1518             if( node->pkt->pkttype == PKT_USER_ID ) {
1519                 if( ++i == idx )
1520                     break;
1521             }
1522         }
1523         if( !node ) {
1524             tty_printf(_("No user id with index %d\n"), idx );
1525             return 0;
1526         }
1527     }
1528     else { /* reset all */
1529         for( i=0, node = keyblock; node; node = node->next ) {
1530             if( node->pkt->pkttype == PKT_USER_ID )
1531                 node->flag &= ~NODFLG_SELUID;
1532         }
1533         return 1;
1534     }
1535     /* and toggle the new index */
1536     for( i=0, node = keyblock; node; node = node->next ) {
1537         if( node->pkt->pkttype == PKT_USER_ID ) {
1538             if( ++i == idx ) {
1539                 if( (node->flag & NODFLG_SELUID) )
1540                     node->flag &= ~NODFLG_SELUID;
1541                 else
1542                     node->flag |= NODFLG_SELUID;
1543             }
1544         }
1545     }
1546
1547     return 1;
1548 }
1549
1550 /****************
1551  * Select secondary keys
1552  * Returns: True if the selection changed;
1553  */
1554 static int
1555 menu_select_key( KBNODE keyblock, int idx )
1556 {
1557     KBNODE node;
1558     int i;
1559
1560     /* first check that the index is valid */
1561     if( idx ) {
1562         for( i=0, node = keyblock; node; node = node->next ) {
1563             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1564                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1565                 if( ++i == idx )
1566                     break;
1567             }
1568         }
1569         if( !node ) {
1570             tty_printf(_("No secondary key with index %d\n"), idx );
1571             return 0;
1572         }
1573     }
1574     else { /* reset all */
1575         for( i=0, node = keyblock; node; node = node->next ) {
1576             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1577                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1578                 node->flag &= ~NODFLG_SELKEY;
1579         }
1580         return 1;
1581     }
1582     /* and set the new index */
1583     for( i=0, node = keyblock; node; node = node->next ) {
1584         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1585             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1586             if( ++i == idx ) {
1587                 if( (node->flag & NODFLG_SELKEY) )
1588                     node->flag &= ~NODFLG_SELKEY;
1589                 else
1590                     node->flag |= NODFLG_SELKEY;
1591             }
1592         }
1593     }
1594
1595     return 1;
1596 }
1597
1598
1599 static int
1600 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1601 {
1602     KBNODE node;
1603     int i=0;
1604
1605     for( node = keyblock; node; node = node->next )
1606         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1607             i++;
1608     return i;
1609 }
1610
1611 static int
1612 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1613 {
1614     KBNODE node;
1615     int i=0;
1616
1617     for( node = keyblock; node; node = node->next )
1618         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1619               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1620             && (node->flag & flag) )
1621             i++;
1622     return i;
1623 }
1624
1625 static int
1626 count_uids( KBNODE keyblock )
1627 {
1628     KBNODE node;
1629     int i=0;
1630
1631     for( node = keyblock; node; node = node->next )
1632         if( node->pkt->pkttype == PKT_USER_ID )
1633             i++;
1634     return i;
1635 }
1636
1637
1638 /****************
1639  * Returns true if there is at least one selected user id
1640  */
1641 static int
1642 count_selected_uids( KBNODE keyblock )
1643 {
1644     return count_uids_with_flag( keyblock, NODFLG_SELUID);
1645 }
1646
1647 static int
1648 count_selected_keys( KBNODE keyblock )
1649 {
1650     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
1651 }
1652
1653 /*
1654  * Ask whether the signature should be revoked.  If the user commits this,
1655  * flag bit MARK_A is set on the signature and the user ID.
1656  */
1657 static void
1658 ask_revoke_sig( KBNODE keyblock, KBNODE node )
1659 {
1660     PKT_signature *sig = node->pkt->pkt.signature;
1661     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
1662
1663     if( !unode ) {
1664         log_error("Oops: no user ID for signature\n");
1665         return;
1666     }
1667
1668     tty_printf(_("user ID: \""));
1669     tty_print_string( unode->pkt->pkt.user_id->name,
1670                       unode->pkt->pkt.user_id->len );
1671     tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
1672                 sig->keyid[1], datestr_from_sig(sig) );
1673
1674     if( cpr_get_answer_is_yes("ask_revoke_sig.one",
1675          _("Create a revocation certificate for this signature? (y/N)")) ) {
1676         node->flag |= NODFLG_MARK_A;
1677         unode->flag |= NODFLG_MARK_A;
1678     }
1679 }
1680
1681 /****************
1682  * Display all user ids of the current public key together with signatures
1683  * done by one of our keys.  Then walk over all this sigs and ask the user
1684  * whether he wants to revoke this signature.
1685  * Return: True when the keyblock has changed.
1686  */
1687 static int
1688 menu_revsig( KBNODE keyblock )
1689 {
1690     PKT_signature *sig;
1691     PKT_public_key *primary_pk;
1692     KBNODE node;
1693     int changed = 0;
1694     int upd_trust = 0;
1695     int rc, any;
1696
1697     /* FIXME: detect duplicates here  */
1698     tty_printf("You have signed these user IDs:\n");
1699     for( node = keyblock; node; node = node->next ) {
1700         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
1701         if( node->pkt->pkttype == PKT_USER_ID ) {
1702             PKT_user_id *uid = node->pkt->pkt.user_id;
1703             /* Hmmm: Should we show only UIDs with a signature? */
1704             tty_printf("     ");
1705             tty_print_string( uid->name, uid->len );
1706             tty_printf("\n");
1707         }
1708         else if( node->pkt->pkttype == PKT_SIGNATURE
1709                 && ((sig = node->pkt->pkt.signature),
1710                      !seckey_available( sig->keyid )  ) ) {
1711             if( (sig->sig_class&~3) == 0x10 ) {
1712                 tty_printf("   signed by %08lX at %s\n",
1713                             sig->keyid[1], datestr_from_sig(sig) );
1714                 node->flag |= NODFLG_SELSIG;
1715             }
1716             else if( sig->sig_class == 0x30 ) {
1717                 tty_printf("   revoked by %08lX at %s\n",
1718                             sig->keyid[1], datestr_from_sig(sig) );
1719             }
1720         }
1721     }
1722
1723     /* ask */
1724     for( node = keyblock; node; node = node->next ) {
1725         if( !(node->flag & NODFLG_SELSIG) )
1726             continue;
1727         ask_revoke_sig( keyblock, node );
1728     }
1729
1730     /* present selected */
1731     any = 0;
1732     for( node = keyblock; node; node = node->next ) {
1733         if( !(node->flag & NODFLG_MARK_A) )
1734             continue;
1735         if( !any ) {
1736             any = 1;
1737             tty_printf("You are about to revoke these signatures:\n");
1738         }
1739         if( node->pkt->pkttype == PKT_USER_ID ) {
1740             PKT_user_id *uid = node->pkt->pkt.user_id;
1741             tty_printf("     ");
1742             tty_print_string( uid->name, uid->len );
1743             tty_printf("\n");
1744         }
1745         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
1746             sig = node->pkt->pkt.signature;
1747             tty_printf("   signed by %08lX at %s\n",
1748                             sig->keyid[1], datestr_from_sig(sig) );
1749         }
1750     }
1751     if( !any )
1752         return 0; /* none selected */
1753
1754     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
1755          _("Really create the revocation certificates? (y/N)")) )
1756         return 0; /* forget it */
1757
1758
1759     /* now we can sign the user ids */
1760   reloop: /* (must use this, because we are modifing the list) */
1761     primary_pk = keyblock->pkt->pkt.public_key;
1762     for( node=keyblock; node; node = node->next ) {
1763         KBNODE unode;
1764         PACKET *pkt;
1765         struct sign_uid_attrib attrib;
1766         PKT_secret_key *sk;
1767
1768         if( !(node->flag & NODFLG_MARK_A)
1769             || node->pkt->pkttype != PKT_SIGNATURE )
1770             continue;
1771         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
1772         assert( unode ); /* we already checked this */
1773
1774         memset( &attrib, 0, sizeof attrib );
1775         node->flag &= ~NODFLG_MARK_A;
1776         sk = m_alloc_secure_clear( sizeof *sk );
1777         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
1778             log_info(_("no secret key\n"));
1779             continue;
1780         }
1781         rc = make_keysig_packet( &sig, primary_pk,
1782                                        unode->pkt->pkt.user_id,
1783                                        NULL,
1784                                        sk,
1785                                        0x30, 0,
1786                                        sign_uid_mk_attrib,
1787                                        &attrib );
1788         free_secret_key(sk);
1789         if( rc ) {
1790             log_error(_("signing failed: %s\n"), g10_errstr(rc));
1791             return changed;
1792         }
1793         changed = 1; /* we changed the keyblock */
1794         upd_trust = 1;
1795
1796         pkt = m_alloc_clear( sizeof *pkt );
1797         pkt->pkttype = PKT_SIGNATURE;
1798         pkt->pkt.signature = sig;
1799         insert_kbnode( unode, new_kbnode(pkt), 0 );
1800         goto reloop;
1801     }
1802
1803     if( upd_trust )
1804         clear_trust_checked_flag( primary_pk );
1805
1806     return changed;
1807 }
1808
1809 /****************
1810  * Revoke some of the secondary keys.
1811  * Hmmm: Should we add a revocation to the secret keyring too?
1812  *       Does its all make sense to duplicate most of the information?
1813  */
1814 static int
1815 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1816 {
1817     PKT_public_key *mainpk;
1818     KBNODE node;
1819     int changed = 0;
1820     int upd_trust = 0;
1821     int rc;
1822
1823   reloop: /* (better this way because we are modifing the keyring) */
1824     mainpk = pub_keyblock->pkt->pkt.public_key;
1825     for( node = pub_keyblock; node; node = node->next ) {
1826         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1827             && (node->flag & NODFLG_SELKEY) ) {
1828             PACKET *pkt;
1829             PKT_signature *sig;
1830             PKT_secret_key *sk;
1831             PKT_public_key *subpk = node->pkt->pkt.public_key;
1832
1833             node->flag &= ~NODFLG_SELKEY;
1834             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
1835             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, 0x28, 0,
1836                                      NULL, NULL );
1837             free_secret_key(sk);
1838             if( rc ) {
1839                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
1840                 return changed;
1841             }
1842             changed = 1; /* we changed the keyblock */
1843             upd_trust = 1;
1844
1845             pkt = m_alloc_clear( sizeof *pkt );
1846             pkt->pkttype = PKT_SIGNATURE;
1847             pkt->pkt.signature = sig;
1848             insert_kbnode( node, new_kbnode(pkt), 0 );
1849             goto reloop;
1850         }
1851     }
1852     commit_kbnode( &pub_keyblock );
1853     /*commit_kbnode( &sec_keyblock );*/
1854
1855     if( upd_trust )
1856         clear_trust_checked_flag( mainpk );
1857
1858     return changed;
1859 }
1860
1861