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