add coprocess facility
[gnupg.git] / g10 / keyedit.c
1 /* keyedit.c - keyedit stuff
2  *      Copyright (C) 1998 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_key_with_all_names( KBNODE keyblock,
44                 int only_marked, int with_fpr, int with_subkeys );
45 static void show_key_and_fingerprint( KBNODE keyblock );
46 static void show_fingerprint( PKT_public_key *pk );
47 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
48 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
49 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
50 static int menu_select_uid( KBNODE keyblock, int index );
51 static int menu_select_key( KBNODE keyblock, int index );
52 static int count_uids( KBNODE keyblock );
53 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
54 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
55 static int count_selected_uids( KBNODE keyblock );
56 static int count_selected_keys( KBNODE keyblock );
57
58
59
60 #define NODFLG_BADSIG (1<<0)  /* bad signature */
61 #define NODFLG_NOKEY  (1<<1)  /* no public key */
62 #define NODFLG_SIGERR (1<<2)  /* other sig error */
63
64 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
65
66 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
67 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
68
69
70 static int
71 get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
72 {
73     int rc;
74
75     *keyblock = NULL;
76     /* search the userid */
77     rc = find_keyblock_byname( kbpos, username );
78     if( rc ) {
79         log_error(_("%s: user not found\n"), username );
80         return rc;
81     }
82
83     /* read the keyblock */
84     rc = read_keyblock( kbpos, keyblock );
85     if( rc )
86         log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
87     return rc;
88 }
89
90
91 /****************
92  * Check the keysigs and set the flags to indicate errors.
93  * Returns true if error found.
94  */
95 static int
96 check_all_keysigs( KBNODE keyblock, int only_selected )
97 {
98     KBNODE kbctx;
99     KBNODE node;
100     int rc;
101     int inv_sigs = 0;
102     int no_key = 0;
103     int oth_err = 0;
104     int has_selfsig = 0;
105     int mis_selfsig = 0;
106     int selected = !only_selected;
107     int anyuid = 0;
108
109     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
110         if( node->pkt->pkttype == PKT_USER_ID ) {
111             PKT_user_id *uid = node->pkt->pkt.user_id;
112
113             if( only_selected )
114                 selected = (node->flag & NODFLG_SELUID);
115             if( selected ) {
116                 tty_printf("uid  ");
117                 tty_print_string( uid->name, uid->len );
118                 tty_printf("\n");
119                 if( anyuid && !has_selfsig )
120                     mis_selfsig++;
121                 has_selfsig = 0;
122                 anyuid = 1;
123             }
124         }
125         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
126                  && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
127             PKT_signature *sig = node->pkt->pkt.signature;
128             int sigrc, selfsig;
129
130             switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
131               case 0:
132                 node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
133                 sigrc = '!';
134                 break;
135               case G10ERR_BAD_SIGN:
136                 node->flag = NODFLG_BADSIG;
137                 sigrc = '-';
138                 inv_sigs++;
139                 break;
140               case G10ERR_NO_PUBKEY:
141                 node->flag = NODFLG_NOKEY;
142                 sigrc = '?';
143                 no_key++;
144                 break;
145               default:
146                 node->flag = NODFLG_SIGERR;
147                 sigrc = '%';
148                 oth_err++;
149                 break;
150             }
151             if( sigrc != '?' ) {
152                 tty_printf("sig%c       %08lX %s   ",
153                         sigrc, sig->keyid[1], datestr_from_sig(sig));
154                 if( sigrc == '%' )
155                     tty_printf("[%s] ", g10_errstr(rc) );
156                 else if( sigrc == '?' )
157                     ;
158                 else if( selfsig ) {
159                     tty_printf( _("[self-signature]") );
160                     if( sigrc == '!' )
161                         has_selfsig = 1;
162                 }
163                 else {
164                     size_t n;
165                     char *p = get_user_id( sig->keyid, &n );
166                     tty_print_string( p, n > 40? 40 : n );
167                     m_free(p);
168                 }
169                 tty_printf("\n");
170                 /* fixme: Should we update the trustdb here */
171             }
172         }
173     }
174     if( !has_selfsig )
175         mis_selfsig++;
176     if( inv_sigs == 1 )
177         tty_printf(_("1 bad signature\n"), inv_sigs );
178     else if( inv_sigs )
179         tty_printf(_("%d bad signatures\n"), inv_sigs );
180     if( no_key == 1 )
181         tty_printf(_("1 signature not checked due to a missing key\n") );
182     else if( no_key )
183         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
184     if( oth_err == 1 )
185         tty_printf(_("1 signature not checked due to an error\n") );
186     else if( oth_err )
187         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
188     if( mis_selfsig == 1 )
189         tty_printf(_("1 user id without valid self-signature detected\n"));
190     else if( mis_selfsig  )
191         tty_printf(_("%d user ids without valid self-signatures detected\n"),
192                                                                     mis_selfsig);
193
194     return inv_sigs || no_key || oth_err || mis_selfsig;
195 }
196
197
198
199 /****************
200  * Loop over all locusr and and sign the uids after asking.
201  * If no user id is marked, all user ids will be signed;
202  * if some user_ids are marked those will be signed.
203  *
204  * fixme: Add support for our proposed sign-all scheme
205  */
206 static int
207 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
208 {
209     int rc = 0;
210     SK_LIST sk_list = NULL;
211     SK_LIST sk_rover = NULL;
212     KBNODE node, uidnode;
213     PKT_public_key *primary_pk;
214     int select_all = !count_selected_uids(keyblock);
215
216     /* build a list of all signators */
217     rc=build_sk_list( locusr, &sk_list, 0, 1 );
218     if( rc )
219         goto leave;
220
221     /* loop over all signaturs */
222     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
223         u32 sk_keyid[2];
224         size_t n;
225         char *p;
226
227         keyid_from_sk( sk_rover->sk, sk_keyid );
228         /* set mark A for all selected user ids */
229         for( node=keyblock; node; node = node->next ) {
230             if( select_all || (node->flag & NODFLG_SELUID) )
231                 node->flag |= NODFLG_MARK_A;
232             else
233                 node->flag &= ~NODFLG_MARK_A;
234         }
235         /* reset mark for uids which are already signed */
236         uidnode = NULL;
237         for( node=keyblock; node; node = node->next ) {
238             if( node->pkt->pkttype == PKT_USER_ID ) {
239                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
240             }
241             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
242                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
243                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
244                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
245                     tty_printf(_("Already signed by key %08lX\n"),
246                                                         (ulong)sk_keyid[1] );
247                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
248                 }
249             }
250         }
251         /* check whether any uids are left for signing */
252         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
253             tty_printf(_("Nothing to sign with key %08lX\n"),
254                                                   (ulong)sk_keyid[1] );
255             continue;
256         }
257         /* Ask whether we realy should sign these user id(s) */
258         tty_printf("\n");
259         show_key_with_all_names( keyblock, 1, 1, 0 );
260         tty_printf("\n");
261         tty_printf(_(
262              "Are you really sure that you want to sign this key\n"
263              "with your key: \""));
264         p = get_user_id( sk_keyid, &n );
265         tty_print_string( p, n );
266         tty_printf("\"\n\n");
267         m_free(p);
268         p = cpr_get("sign_uid.really", _("Really sign? "));
269         cpr_kill_prompt();
270         if( !answer_is_yes(p) ) {
271             m_free(p);
272             continue; /* No */
273         }
274         m_free(p);
275         /* now we can sign the user ids */
276       reloop: /* (must use this, because we are modifing the list) */
277         primary_pk = NULL;
278         for( node=keyblock; node; node = node->next ) {
279             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
280                 primary_pk = node->pkt->pkt.public_key;
281             else if( node->pkt->pkttype == PKT_USER_ID
282                      && (node->flag & NODFLG_MARK_A) ) {
283                 PACKET *pkt;
284                 PKT_signature *sig;
285
286                 assert( primary_pk );
287                 node->flag &= ~NODFLG_MARK_A;
288                 rc = make_keysig_packet( &sig, primary_pk,
289                                                node->pkt->pkt.user_id,
290                                                NULL,
291                                                sk_rover->sk,
292                                                0x10, 0, NULL, NULL );
293                 if( rc ) {
294                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
295                     goto leave;
296                 }
297                 *ret_modified = 1; /* we changed the keyblock */
298
299                 pkt = m_alloc_clear( sizeof *pkt );
300                 pkt->pkttype = PKT_SIGNATURE;
301                 pkt->pkt.signature = sig;
302                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
303                 goto reloop;
304             }
305         }
306     } /* end loop over signators */
307
308   leave:
309     release_sk_list( sk_list );
310     return rc;
311 }
312
313
314
315
316 /****************
317  * Delete a public or secret key from a keyring.
318  */
319 int
320 delete_key( const char *username, int secret )
321 {
322     int rc = 0;
323     KBNODE keyblock = NULL;
324     KBNODE node;
325     KBPOS kbpos;
326     PKT_public_key *pk = NULL;
327     PKT_secret_key *sk = NULL;
328     u32 keyid[2];
329     int okay=0;
330
331     /* search the userid */
332     rc = secret? find_secret_keyblock_byname( &kbpos, username )
333                : find_keyblock_byname( &kbpos, username );
334     if( rc ) {
335         log_error(_("%s: user not found\n"), username );
336         goto leave;
337     }
338
339     /* read the keyblock */
340     rc = read_keyblock( &kbpos, &keyblock );
341     if( rc ) {
342         log_error("%s: read problem: %s\n", username, g10_errstr(rc) );
343         goto leave;
344     }
345
346     /* get the keyid from the keyblock */
347     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
348     if( !node ) {
349         log_error("Oops; key not found anymore!\n");
350         rc = G10ERR_GENERAL;
351         goto leave;
352     }
353
354     if( secret ) {
355         sk = node->pkt->pkt.secret_key;
356         keyid_from_sk( sk, keyid );
357     }
358     else {
359         pk = node->pkt->pkt.public_key;
360         keyid_from_pk( pk, keyid );
361         rc = seckey_available( keyid );
362         if( !rc ) {
363             log_error(_(
364             "there is a secret key for this public key!\n"));
365             log_info(_(
366             "use option \"--delete-secret-key\" to delete it first.\n"));
367             rc = -1;
368         }
369         else if( rc != G10ERR_NO_SECKEY )
370             log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
371         else
372             rc = 0;
373     }
374
375     if( rc )
376         rc = 0;
377     else if( opt.batch && secret )
378         log_error(_("can't do that in batch-mode\n"));
379     else if( opt.batch && opt.answer_yes )
380         okay++;
381     else if( opt.batch )
382         log_error(_("can't do that in batch-mode without \"--yes\"\n"));
383     else {
384         char *p;
385         size_t n;
386
387         if( secret )
388             tty_printf("sec  %4u%c/%08lX %s   ",
389                       nbits_from_sk( sk ),
390                       pubkey_letter( sk->pubkey_algo ),
391                       keyid[1], datestr_from_sk(sk) );
392         else
393             tty_printf("pub  %4u%c/%08lX %s   ",
394                       nbits_from_pk( pk ),
395                       pubkey_letter( pk->pubkey_algo ),
396                       keyid[1], datestr_from_pk(pk) );
397         p = get_user_id( keyid, &n );
398         tty_print_string( p, n );
399         m_free(p);
400         tty_printf("\n\n");
401
402         p = cpr_get( secret? "delete_key.secret.really":"delete_key.really",
403                         _("Delete this key from the keyring? "));
404         cpr_kill_prompt();
405         if( !cpr_enabled() && secret && answer_is_yes(p)) {
406             /* I think it is not required to check a passphrase; if
407              * the user is so stupid as to let others access his secret keyring
408              * (and has no backup) - it is up him to read some very
409              * basic texts about security.
410              */
411             m_free(p);
412             p = tty_get(_("This is a secret key! - really delete? "));
413         }
414         if( answer_is_yes(p) )
415             okay++;
416         m_free(p);
417     }
418
419
420     if( okay ) {
421         rc = delete_keyblock( &kbpos );
422         if( rc ) {
423             log_error("delete_keyblock failed: %s\n", g10_errstr(rc) );
424             goto leave;
425         }
426     }
427
428   leave:
429     release_kbnode( keyblock );
430     return rc;
431 }
432
433
434 /****************
435  * Change the passphrase of the primary and all secondary keys.
436  * We use only one passphrase for all keys.
437  */
438 static int
439 change_passphrase( KBNODE keyblock )
440 {
441     int rc = 0;
442     int changed=0;
443     KBNODE node;
444     PKT_secret_key *sk;
445     char *passphrase = NULL;
446
447     node = find_kbnode( keyblock, PKT_SECRET_KEY );
448     if( !node ) {
449         log_error("Oops; secret key not found anymore!\n");
450         goto leave;
451     }
452     sk = node->pkt->pkt.secret_key;
453
454     switch( is_secret_key_protected( sk ) ) {
455       case -1:
456         rc = G10ERR_PUBKEY_ALGO;
457         break;
458       case 0:
459         tty_printf(_("This key is not protected.\n"));
460         break;
461       default:
462         tty_printf(_("Key is protected.\n"));
463         rc = check_secret_key( sk );
464         if( !rc )
465             passphrase = get_last_passphrase();
466         break;
467     }
468
469     /* unprotect all subkeys (use the supplied passphrase or ask)*/
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             set_next_passphrase( passphrase );
474             rc = check_secret_key( subsk );
475         }
476     }
477
478     if( rc )
479         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
480     else {
481         DEK *dek = NULL;
482         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
483
484         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
485
486         set_next_passphrase( NULL );
487         for(;;) {
488             s2k->mode = 1;
489             s2k->hash_algo = DIGEST_ALGO_RMD160;
490             dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 );
491             if( !dek ) {
492                 tty_printf(_("passphrase not correctly repeated; try again.\n"));
493             }
494             else if( !dek->keylen ) {
495                 rc = 0;
496                 tty_printf(_( "You don't want a passphrase -"
497                             " this is probably a *bad* idea!\n\n"));
498                 if( cpr_get_answer_is_yes("change_passwd.empty",
499                                _("Do you really want to do this? ")))
500                     changed++;
501                 break;
502             }
503             else { /* okay */
504                 sk->protect.algo = dek->algo;
505                 sk->protect.s2k = *s2k;
506                 rc = protect_secret_key( sk, dek );
507                 for(node=keyblock; !rc && node; node = node->next ) {
508                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
509                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
510                         subsk->protect.algo = dek->algo;
511                         subsk->protect.s2k = *s2k;
512                         rc = protect_secret_key( subsk, dek );
513                     }
514                 }
515                 if( rc )
516                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
517                 else
518                     changed++;
519                 break;
520             }
521         }
522         m_free(s2k);
523         m_free(dek);
524     }
525
526   leave:
527     m_free( passphrase );
528     set_next_passphrase( NULL );
529     return changed && !rc;
530 }
531
532
533
534
535 /****************
536  * Menu driven key editor
537  *
538  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
539  */
540
541 void
542 keyedit_menu( const char *username, STRLIST locusr )
543 {
544     enum cmdids { cmdNONE = 0,
545            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
546            cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
547            cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST,
548            cmdNOP };
549     static struct { const char *name;
550                     enum cmdids id;
551                     int need_sk;
552                     const char *desc;
553                   } cmds[] = {
554         { N_("quit")    , cmdQUIT   , 0, N_("quit this menu") },
555         { N_("q")       , cmdQUIT   , 0, NULL   },
556         { N_("save")    , cmdSAVE   , 0, N_("save and quit") },
557         { N_("help")    , cmdHELP   , 0, N_("show this help") },
558         {    "?"        , cmdHELP   , 0, NULL   },
559         { N_("fpr")     , cmdFPR    , 0, N_("show fingerprint") },
560         { N_("list")    , cmdLIST   , 0, N_("list key and user ids") },
561         { N_("l")       , cmdLIST   , 0, NULL   },
562         { N_("uid")     , cmdSELUID , 0, N_("select user id N") },
563         { N_("key")     , cmdSELKEY , 0, N_("select secondary key N") },
564         { N_("check")   , cmdCHECK  , 0, N_("list signatures") },
565         { N_("c")       , cmdCHECK  , 0, NULL },
566         { N_("sign")    , cmdSIGN   , 0, N_("sign the key") },
567         { N_("s")       , cmdSIGN   , 0, NULL },
568         { N_("debug")   , cmdDEBUG  , 0, NULL },
569         { N_("adduid")  , cmdADDUID , 1, N_("add a user id") },
570         { N_("deluid")  , cmdDELUID , 0, N_("delete user id") },
571         { N_("addkey")  , cmdADDKEY , 1, N_("add a secondary key") },
572         { N_("delkey")  , cmdDELKEY , 0, N_("delete a secondary key") },
573         { N_("toggle")  , cmdTOGGLE , 1, N_("toggle between secret "
574                                             "and public key listing") },
575         { N_("t"     )  , cmdTOGGLE , 1, NULL },
576         { N_("passwd")  , cmdPASSWD , 1, N_("change the passphrase") },
577         { N_("trust")   , cmdTRUST , 0, N_("change the ownertrust") },
578
579     { NULL, cmdNONE } };
580     enum cmdids cmd;
581     int rc = 0;
582     KBNODE keyblock = NULL;
583     KBPOS keyblockpos;
584     KBNODE sec_keyblock = NULL;
585     KBPOS sec_keyblockpos;
586     KBNODE cur_keyblock;
587     char *answer = NULL;
588     int redisplay = 1;
589     int modified = 0;
590     int sec_modified = 0;
591     int toggle;
592
593
594     if( opt.batch ) {
595         log_error(_("can't do that in batch-mode\n"));
596         goto leave;
597     }
598
599     /* first try to locate it as secret key */
600     rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
601     if( !rc ) {
602         rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
603         if( rc ) {
604             log_error("%s: secret keyblock read problem: %s\n",
605                                             username, g10_errstr(rc));
606             goto leave;
607         }
608     }
609
610     /* and now get the public key */
611     rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
612     if( rc )
613         goto leave;
614
615     if( sec_keyblock ) { /* check that they match */
616         /* FIXME: check that they both match */
617         tty_printf(_("Secret key is available.\n"));
618     }
619
620     toggle = 0;
621     cur_keyblock = keyblock;
622     for(;;) { /* main loop */
623         int i, arg_number;
624         char *p;
625
626         tty_printf("\n");
627         if( redisplay ) {
628             show_key_with_all_names( cur_keyblock, 0, 0, 1 );
629             tty_printf("\n");
630             redisplay = 0;
631         }
632         m_free(answer);
633         answer = cpr_get("keyedit.cmd", _("Command> "));
634         cpr_kill_prompt();
635         trim_spaces(answer);
636
637         arg_number = 0;
638         if( !*answer )
639             cmd = cmdLIST;
640         else if( isdigit( *answer ) ) {
641             cmd = cmdSELUID;
642             arg_number = atoi(answer);
643         }
644         else {
645             if( (p=strchr(answer,' ')) ) {
646                 *p++ = 0;
647                 trim_spaces(answer);
648                 trim_spaces(p);
649                 arg_number = atoi(p);
650             }
651
652             for(i=0; cmds[i].name; i++ )
653                 if( !stricmp( answer, cmds[i].name ) )
654                     break;
655             if( cmds[i].need_sk && !sec_keyblock ) {
656                 tty_printf(_("Need the secret key to to this.\n"));
657                 cmd = cmdNOP;
658             }
659             else
660                 cmd = cmds[i].id;
661         }
662         switch( cmd )  {
663           case cmdHELP:
664             for(i=0; cmds[i].name; i++ ) {
665                 if( cmds[i].need_sk && !sec_keyblock )
666                     ; /* skip if we do not have the secret key */
667                 else if( cmds[i].desc )
668                     tty_printf("%-10s %s\n", cmds[i].name, cmds[i].desc );
669             }
670             break;
671
672           case cmdQUIT:
673             if( !modified )
674                 goto leave;
675             if( !cpr_get_answer_is_yes("keyedit.save",_("Save changes? ")) ) {
676                 if( cpr_enabled()
677                     || tty_get_answer_is_yes(_("Quit without saving? ")) )
678                     goto leave;
679                 break;
680             }
681             /* fall thru */
682           case cmdSAVE:
683             if( modified ) {
684                 rc = update_keyblock( &keyblockpos, keyblock );
685                 if( rc ) {
686                     log_error(_("update failed: %s\n"), g10_errstr(rc) );
687                     break;
688                 }
689                 if( sec_modified ) {
690                     rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
691                     if( rc ) {
692                         log_error(_("update secret failed: %s\n"),
693                                                             g10_errstr(rc) );
694                         break;
695                     }
696                 }
697                 /* FIXME: UPDATE/INVALIDATE trustdb !! */
698             }
699             else
700                 tty_printf(_("Key not changed so no update needed.\n"));
701             goto leave;
702
703           case cmdLIST:
704             redisplay = 1;
705             break;
706
707           case cmdFPR:
708             show_key_and_fingerprint( keyblock );
709             break;
710
711           case cmdSELUID:
712             if( menu_select_uid( cur_keyblock, arg_number ) )
713                 redisplay = 1;
714             break;
715
716           case cmdSELKEY:
717             if( menu_select_key( cur_keyblock, arg_number ) )
718                 redisplay = 1;
719             break;
720
721           case cmdCHECK:
722             /* we can only do this with the public key becuase the
723              * check functions can't cope with secret keys and it
724              * is questionable whether this would make sense at all */
725             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
726             break;
727
728           case cmdSIGN: /* sign (only the public key) */
729             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
730                 if( !tty_get_answer_is_yes(_("Really sign all user ids? ")) ) {
731                     tty_printf(_("Hint: Select the user ids to sign\n"));
732                     break;
733                 }
734             }
735             sign_uids( keyblock, locusr, &modified );
736             break;
737
738           case cmdDEBUG:
739             dump_kbnode( cur_keyblock );
740             break;
741
742           case cmdTOGGLE:
743             toggle = !toggle;
744             cur_keyblock = toggle? sec_keyblock : keyblock;
745             redisplay = 1;
746             break;
747
748           case cmdADDUID:
749             if( menu_adduid( keyblock, sec_keyblock ) ) {
750                 redisplay = 1;
751                 sec_modified = modified = 1;
752             }
753             break;
754
755           case cmdDELUID: {
756                 int n1;
757
758                 if( !(n1=count_selected_uids(keyblock)) )
759                     tty_printf(_("You must select at least one user id.\n"));
760                 else if( count_uids(keyblock) - n1 < 1 )
761                     tty_printf(_("You can't delete the last user id!\n"));
762                 else if( tty_get_answer_is_yes(
763                         n1 > 1? _("Really remove all selected user ids? ")
764                               : _("Really remove this user id? ")
765                        ) ) {
766                     menu_deluid( keyblock, sec_keyblock );
767                     redisplay = 1;
768                     modified = 1;
769                     if( sec_keyblock )
770                        sec_modified = 1;
771                 }
772             }
773             break;
774
775           case cmdADDKEY:
776             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
777                 redisplay = 1;
778                 sec_modified = modified = 1;
779             }
780             break;
781
782
783           case cmdDELKEY: {
784                 int n1;
785
786                 if( !(n1=count_selected_keys( keyblock )) )
787                     tty_printf(_("You must select at least one key.\n"));
788                 else if( sec_keyblock && !tty_get_answer_is_yes(
789                        n1 > 1?
790                         _("Do you really want to delete the selected keys? "):
791                         _("Do you really want to delete this key? ")
792                        ))
793                     ;
794                 else {
795                     menu_delkey( keyblock, sec_keyblock );
796                     redisplay = 1;
797                     modified = 1;
798                     if( sec_keyblock )
799                        sec_modified = 1;
800                 }
801             }
802             break;
803
804           case cmdPASSWD:
805             if( change_passphrase( sec_keyblock ) )
806                 sec_modified = 1;
807             break;
808
809           case cmdTRUST:
810             show_key_with_all_names( keyblock, 0, 0, 1 );
811             tty_printf("\n");
812             if( edit_ownertrust( find_kbnode( keyblock,
813                       PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
814                 redisplay = 1;
815             /* we don't need to set modified here, as the trustvalues
816              * are updated immediately */
817             break;
818
819           case cmdNOP:
820             break;
821
822           default:
823             tty_printf("\n");
824             tty_printf(_("Invalid command  (try \"help\")\n"));
825             break;
826         }
827     } /* end main loop */
828
829   leave:
830     release_kbnode( keyblock );
831     release_kbnode( sec_keyblock );
832     m_free(answer);
833 }
834
835
836
837 /****************
838  * Display the key a the user ids, if only_marked is true, do only
839  * so for user ids with mark A flag set and dont display the index number
840  */
841 static void
842 show_key_with_all_names( KBNODE keyblock, int only_marked,
843                          int with_fpr, int with_subkeys )
844 {
845     KBNODE node;
846     int i;
847
848     /* the keys */
849     for( node = keyblock; node; node = node->next ) {
850         if( node->pkt->pkttype == PKT_PUBLIC_KEY
851             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
852             PKT_public_key *pk = node->pkt->pkt.public_key;
853             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s",
854                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
855                           (node->flag & NODFLG_SELKEY)? '*':' ',
856                           nbits_from_pk( pk ),
857                           pubkey_letter( pk->pubkey_algo ),
858                           (ulong)keyid_from_pk(pk,NULL),
859                           datestr_from_pk(pk),
860                           expirestr_from_pk(pk) );
861             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
862                 int otrust, trust;
863                 trust = query_trust_info(pk);
864                 otrust = get_ownertrust_info( pk->local_id );
865                 tty_printf(" trust: %c/%c", otrust, trust );
866                 if( with_fpr  )
867                     show_fingerprint( pk );
868             }
869             tty_printf("\n");
870         }
871         else if( node->pkt->pkttype == PKT_SECRET_KEY
872             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
873             PKT_secret_key *sk = node->pkt->pkt.secret_key;
874             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s\n",
875                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
876                           (node->flag & NODFLG_SELKEY)? '*':' ',
877                           nbits_from_sk( sk ),
878                           pubkey_letter( sk->pubkey_algo ),
879                           (ulong)keyid_from_sk(sk,NULL),
880                           datestr_from_sk(sk),
881                           expirestr_from_sk(sk) );
882         }
883     }
884     /* the user ids */
885     i = 0;
886     for( node = keyblock; node; node = node->next ) {
887         if( node->pkt->pkttype == PKT_USER_ID ) {
888             PKT_user_id *uid = node->pkt->pkt.user_id;
889             ++i;
890             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
891                 if( only_marked )
892                    tty_printf("     ");
893                 else if( node->flag & NODFLG_SELUID )
894                    tty_printf("(%d)* ", i);
895                 else
896                    tty_printf("(%d)  ", i);
897                 tty_print_string( uid->name, uid->len );
898                 tty_printf("\n");
899             }
900         }
901     }
902 }
903
904 static void
905 show_key_and_fingerprint( KBNODE keyblock )
906 {
907     KBNODE node;
908     PKT_public_key *pk = NULL;
909
910     for( node = keyblock; node; node = node->next ) {
911         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
912             pk = node->pkt->pkt.public_key;
913             tty_printf("pub  %4u%c/%08lX %s ",
914                           nbits_from_pk( pk ),
915                           pubkey_letter( pk->pubkey_algo ),
916                           (ulong)keyid_from_pk(pk,NULL),
917                           datestr_from_pk(pk) );
918         }
919         else if( node->pkt->pkttype == PKT_USER_ID ) {
920             PKT_user_id *uid = node->pkt->pkt.user_id;
921             tty_print_string( uid->name, uid->len );
922             break;
923         }
924     }
925     tty_printf("\n");
926     if( pk )
927         show_fingerprint( pk );
928 }
929
930
931 static void
932 show_fingerprint( PKT_public_key *pk )
933 {
934     byte *array, *p;
935     size_t i, n;
936
937     p = array = fingerprint_from_pk( pk, NULL, &n );
938     tty_printf("             Fingerprint:");
939     if( n == 20 ) {
940         for(i=0; i < n ; i++, i++, p += 2 ) {
941             if( i == 10 )
942                 tty_printf(" ");
943             tty_printf(" %02X%02X", *p, p[1] );
944         }
945     }
946     else {
947         for(i=0; i < n ; i++, p++ ) {
948             if( i && !(i%8) )
949                 tty_printf(" ");
950             tty_printf(" %02X", *p );
951         }
952     }
953     tty_printf("\n");
954     m_free(array);
955 }
956
957
958 /****************
959  * Ask for a new user id , do the selfsignature and put it into
960  * both keyblocks.
961  * Return true if there is a new user id
962  */
963 static int
964 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
965 {
966     PKT_user_id *uid;
967     PKT_public_key *pk=NULL;
968     PKT_secret_key *sk=NULL;
969     PKT_signature *sig=NULL;
970     PACKET *pkt;
971     KBNODE node;
972     KBNODE pub_where=NULL, sec_where=NULL;
973     int rc;
974
975     uid = generate_user_id();
976     if( !uid )
977         return 0;
978
979     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
980         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
981             pk = node->pkt->pkt.public_key;
982         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
983             break;
984     }
985     if( !node ) /* no subkey */
986         pub_where = NULL;
987     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
988         if( node->pkt->pkttype == PKT_SECRET_KEY )
989             sk = node->pkt->pkt.secret_key;
990         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
991             break;
992     }
993     if( !node ) /* no subkey */
994         sec_where = NULL;
995     assert(pk && sk );
996
997     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
998                              keygen_add_std_prefs, sk );
999     if( rc ) {
1000         log_error("signing failed: %s\n", g10_errstr(rc) );
1001         free_user_id(uid);
1002         return 0;
1003     }
1004
1005     /* insert/append to secret keyblock */
1006     pkt = m_alloc_clear( sizeof *pkt );
1007     pkt->pkttype = PKT_USER_ID;
1008     pkt->pkt.user_id = copy_user_id(NULL, uid);
1009     node = new_kbnode(pkt);
1010     if( sec_where )
1011         insert_kbnode( sec_where, node, 0 );
1012     else
1013         add_kbnode( sec_keyblock, node );
1014     pkt = m_alloc_clear( sizeof *pkt );
1015     pkt->pkttype = PKT_SIGNATURE;
1016     pkt->pkt.signature = copy_signature(NULL, sig);
1017     if( sec_where )
1018         insert_kbnode( node, new_kbnode(pkt), 0 );
1019     else
1020         add_kbnode( sec_keyblock, new_kbnode(pkt) );
1021     /* insert/append to public keyblock */
1022     pkt = m_alloc_clear( sizeof *pkt );
1023     pkt->pkttype = PKT_USER_ID;
1024     pkt->pkt.user_id = uid;
1025     node = new_kbnode(pkt);
1026     if( pub_where )
1027         insert_kbnode( pub_where, node, 0 );
1028     else
1029         add_kbnode( pub_keyblock, node );
1030     pkt = m_alloc_clear( sizeof *pkt );
1031     pkt->pkttype = PKT_SIGNATURE;
1032     pkt->pkt.signature = copy_signature(NULL, sig);
1033     if( pub_where )
1034         insert_kbnode( node, new_kbnode(pkt), 0 );
1035     else
1036         add_kbnode( pub_keyblock, new_kbnode(pkt) );
1037     return 1;
1038 }
1039
1040
1041 /****************
1042  * Remove all selceted userids from the keyrings
1043  */
1044 static void
1045 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1046 {
1047     KBNODE node;
1048     int selected=0;
1049
1050     for( node = pub_keyblock; node; node = node->next ) {
1051         if( node->pkt->pkttype == PKT_USER_ID ) {
1052             selected = node->flag & NODFLG_SELUID;
1053             if( selected ) {
1054                 delete_kbnode( node );
1055                 if( sec_keyblock ) {
1056                     KBNODE snode;
1057                     int s_selected = 0;
1058                     PKT_user_id *uid = node->pkt->pkt.user_id;
1059                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1060                         if( snode->pkt->pkttype == PKT_USER_ID ) {
1061                             PKT_user_id *suid = snode->pkt->pkt.user_id;
1062
1063                             s_selected =
1064                                 (uid->len == suid->len
1065                                  && !memcmp( uid->name, suid->name, uid->len));
1066                             if( s_selected )
1067                                 delete_kbnode( snode );
1068                         }
1069                         else if( s_selected
1070                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1071                             delete_kbnode( snode );
1072                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1073                             s_selected = 0;
1074                     }
1075                 }
1076             }
1077         }
1078         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1079             delete_kbnode( node );
1080         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1081             selected = 0;
1082     }
1083     commit_kbnode( &pub_keyblock );
1084     if( sec_keyblock )
1085         commit_kbnode( &sec_keyblock );
1086 }
1087
1088
1089 /****************
1090  * Remove some of the secondary keys
1091  */
1092 static void
1093 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1094 {
1095     KBNODE node;
1096     int selected=0;
1097
1098     for( node = pub_keyblock; node; node = node->next ) {
1099         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1100             selected = node->flag & NODFLG_SELKEY;
1101             if( selected ) {
1102                 delete_kbnode( node );
1103                 if( sec_keyblock ) {
1104                     KBNODE snode;
1105                     int s_selected = 0;
1106                     u32 ki[2];
1107
1108                     keyid_from_pk( node->pkt->pkt.public_key, ki );
1109                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1110                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1111                             u32 ki2[2];
1112
1113                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1114                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1115                             if( s_selected )
1116                                 delete_kbnode( snode );
1117                         }
1118                         else if( s_selected
1119                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1120                             delete_kbnode( snode );
1121                         else
1122                             s_selected = 0;
1123                     }
1124                 }
1125             }
1126         }
1127         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1128             delete_kbnode( node );
1129         else
1130             selected = 0;
1131     }
1132     commit_kbnode( &pub_keyblock );
1133     if( sec_keyblock )
1134         commit_kbnode( &sec_keyblock );
1135 }
1136
1137
1138 /****************
1139  * Select one user id or remove all selection if index is 0.
1140  * Returns: True if the selection changed;
1141  */
1142 static int
1143 menu_select_uid( KBNODE keyblock, int index )
1144 {
1145     KBNODE node;
1146     int i;
1147
1148     /* first check that the index is valid */
1149     if( index ) {
1150         for( i=0, node = keyblock; node; node = node->next ) {
1151             if( node->pkt->pkttype == PKT_USER_ID ) {
1152                 if( ++i == index )
1153                     break;
1154             }
1155         }
1156         if( !node ) {
1157             tty_printf(_("No user id with index %d\n"), index );
1158             return 0;
1159         }
1160     }
1161     else { /* reset all */
1162         for( i=0, node = keyblock; node; node = node->next ) {
1163             if( node->pkt->pkttype == PKT_USER_ID )
1164                 node->flag &= ~NODFLG_SELUID;
1165         }
1166         return 1;
1167     }
1168     /* and toggle the new index */
1169     for( i=0, node = keyblock; node; node = node->next ) {
1170         if( node->pkt->pkttype == PKT_USER_ID ) {
1171             if( ++i == index )
1172                 if( (node->flag & NODFLG_SELUID) )
1173                     node->flag &= ~NODFLG_SELUID;
1174                 else
1175                     node->flag |= NODFLG_SELUID;
1176         }
1177     }
1178
1179     return 1;
1180 }
1181
1182 /****************
1183  * Select secondary keys
1184  * Returns: True if the selection changed;
1185  */
1186 static int
1187 menu_select_key( KBNODE keyblock, int index )
1188 {
1189     KBNODE node;
1190     int i;
1191
1192     /* first check that the index is valid */
1193     if( index ) {
1194         for( i=0, node = keyblock; node; node = node->next ) {
1195             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1196                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1197                 if( ++i == index )
1198                     break;
1199             }
1200         }
1201         if( !node ) {
1202             tty_printf(_("No secondary key with index %d\n"), index );
1203             return 0;
1204         }
1205     }
1206     else { /* reset all */
1207         for( i=0, node = keyblock; node; node = node->next ) {
1208             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1209                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1210                 node->flag &= ~NODFLG_SELKEY;
1211         }
1212         return 1;
1213     }
1214     /* and set the new index */
1215     for( i=0, node = keyblock; node; node = node->next ) {
1216         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1217             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1218             if( ++i == index )
1219                 if( (node->flag & NODFLG_SELKEY) )
1220                     node->flag &= ~NODFLG_SELKEY;
1221                 else
1222                     node->flag |= NODFLG_SELKEY;
1223         }
1224     }
1225
1226     return 1;
1227 }
1228
1229
1230 static int
1231 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1232 {
1233     KBNODE node;
1234     int i=0;
1235
1236     for( node = keyblock; node; node = node->next )
1237         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1238             i++;
1239     return i;
1240 }
1241
1242 static int
1243 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1244 {
1245     KBNODE node;
1246     int i=0;
1247
1248     for( node = keyblock; node; node = node->next )
1249         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1250               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1251             && (node->flag & flag) )
1252             i++;
1253     return i;
1254 }
1255
1256 static int
1257 count_uids( KBNODE keyblock )
1258 {
1259     KBNODE node;
1260     int i=0;
1261
1262     for( node = keyblock; node; node = node->next )
1263         if( node->pkt->pkttype == PKT_USER_ID )
1264             i++;
1265     return i;
1266 }
1267
1268
1269 /****************
1270  * Returns true if there is at least one selected user id
1271  */
1272 static int
1273 count_selected_uids( KBNODE keyblock )
1274 {
1275     return count_uids_with_flag( keyblock, NODFLG_SELUID);
1276 }
1277
1278 static int
1279 count_selected_keys( KBNODE keyblock )
1280 {
1281     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
1282 }
1283