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