bug fix release
[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_prefs( KBNODE keyblock, PKT_user_id *uid );
44 static void show_key_with_all_names( KBNODE keyblock,
45             int only_marked, int with_fpr, int with_subkeys, int with_prefs );
46 static void show_key_and_fingerprint( KBNODE keyblock );
47 static void show_fingerprint( PKT_public_key *pk );
48 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
49 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
50 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
51 static int menu_select_uid( KBNODE keyblock, int index );
52 static int menu_select_key( KBNODE keyblock, int index );
53 static int count_uids( KBNODE keyblock );
54 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
55 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
56 static int count_selected_uids( KBNODE keyblock );
57 static int count_selected_keys( KBNODE keyblock );
58
59
60
61 #define NODFLG_BADSIG (1<<0)  /* bad signature */
62 #define NODFLG_NOKEY  (1<<1)  /* no public key */
63 #define NODFLG_SIGERR (1<<2)  /* other sig error */
64
65 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
66
67 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
68 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
69
70
71 static int
72 get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
73 {
74     int rc;
75
76     *keyblock = NULL;
77     /* search the userid */
78     rc = find_keyblock_byname( kbpos, username );
79     if( rc ) {
80         log_error(_("%s: user not found\n"), username );
81         return rc;
82     }
83
84     /* read the keyblock */
85     rc = read_keyblock( kbpos, keyblock );
86     if( rc )
87         log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
88     return rc;
89 }
90
91
92 /****************
93  * Check the keysigs and set the flags to indicate errors.
94  * Returns true if error found.
95  */
96 static int
97 check_all_keysigs( KBNODE keyblock, int only_selected )
98 {
99     KBNODE kbctx;
100     KBNODE node;
101     int rc;
102     int inv_sigs = 0;
103     int no_key = 0;
104     int oth_err = 0;
105     int has_selfsig = 0;
106     int mis_selfsig = 0;
107     int selected = !only_selected;
108     int anyuid = 0;
109
110     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
111         if( node->pkt->pkttype == PKT_USER_ID ) {
112             PKT_user_id *uid = node->pkt->pkt.user_id;
113
114             if( only_selected )
115                 selected = (node->flag & NODFLG_SELUID);
116             if( selected ) {
117                 tty_printf("uid  ");
118                 tty_print_string( uid->name, uid->len );
119                 tty_printf("\n");
120                 if( anyuid && !has_selfsig )
121                     mis_selfsig++;
122                 has_selfsig = 0;
123                 anyuid = 1;
124             }
125         }
126         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
127                  && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
128             PKT_signature *sig = node->pkt->pkt.signature;
129             int sigrc, selfsig;
130
131             switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
132               case 0:
133                 node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
134                 sigrc = '!';
135                 break;
136               case G10ERR_BAD_SIGN:
137                 node->flag = NODFLG_BADSIG;
138                 sigrc = '-';
139                 inv_sigs++;
140                 break;
141               case G10ERR_NO_PUBKEY:
142                 node->flag = NODFLG_NOKEY;
143                 sigrc = '?';
144                 no_key++;
145                 break;
146               default:
147                 node->flag = NODFLG_SIGERR;
148                 sigrc = '%';
149                 oth_err++;
150                 break;
151             }
152             if( sigrc != '?' ) {
153                 tty_printf("sig%c       %08lX %s   ",
154                         sigrc, sig->keyid[1], datestr_from_sig(sig));
155                 if( sigrc == '%' )
156                     tty_printf("[%s] ", g10_errstr(rc) );
157                 else if( sigrc == '?' )
158                     ;
159                 else if( selfsig ) {
160                     tty_printf( _("[self-signature]") );
161                     if( sigrc == '!' )
162                         has_selfsig = 1;
163                 }
164                 else {
165                     size_t n;
166                     char *p = get_user_id( sig->keyid, &n );
167                     tty_print_string( p, n > 40? 40 : n );
168                     m_free(p);
169                 }
170                 tty_printf("\n");
171                 /* fixme: Should we update the trustdb here */
172             }
173         }
174     }
175     if( !has_selfsig )
176         mis_selfsig++;
177     if( inv_sigs == 1 )
178         tty_printf(_("1 bad signature\n"), inv_sigs );
179     else if( inv_sigs )
180         tty_printf(_("%d bad signatures\n"), inv_sigs );
181     if( no_key == 1 )
182         tty_printf(_("1 signature not checked due to a missing key\n") );
183     else if( no_key )
184         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
185     if( oth_err == 1 )
186         tty_printf(_("1 signature not checked due to an error\n") );
187     else if( oth_err )
188         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
189     if( mis_selfsig == 1 )
190         tty_printf(_("1 user id without valid self-signature detected\n"));
191     else if( mis_selfsig  )
192         tty_printf(_("%d user ids without valid self-signatures detected\n"),
193                                                                     mis_selfsig);
194
195     return inv_sigs || no_key || oth_err || mis_selfsig;
196 }
197
198
199
200 /****************
201  * Loop over all locusr and and sign the uids after asking.
202  * If no user id is marked, all user ids will be signed;
203  * if some user_ids are marked those will be signed.
204  *
205  * fixme: Add support for our proposed sign-all scheme
206  */
207 static int
208 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
209 {
210     int rc = 0;
211     SK_LIST sk_list = NULL;
212     SK_LIST sk_rover = NULL;
213     KBNODE node, uidnode;
214     PKT_public_key *primary_pk;
215     int select_all = !count_selected_uids(keyblock);
216
217     /* build a list of all signators */
218     rc=build_sk_list( locusr, &sk_list, 0, 1 );
219     if( rc )
220         goto leave;
221
222     /* loop over all signaturs */
223     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
224         u32 sk_keyid[2];
225         size_t n;
226         char *p;
227
228         keyid_from_sk( sk_rover->sk, sk_keyid );
229         /* set mark A for all selected user ids */
230         for( node=keyblock; node; node = node->next ) {
231             if( select_all || (node->flag & NODFLG_SELUID) )
232                 node->flag |= NODFLG_MARK_A;
233             else
234                 node->flag &= ~NODFLG_MARK_A;
235         }
236         /* reset mark for uids which are already signed */
237         uidnode = NULL;
238         for( node=keyblock; node; node = node->next ) {
239             if( node->pkt->pkttype == PKT_USER_ID ) {
240                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
241             }
242             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
243                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
244                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
245                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
246                     tty_printf(_("Already signed by key %08lX\n"),
247                                                         (ulong)sk_keyid[1] );
248                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
249                 }
250             }
251         }
252         /* check whether any uids are left for signing */
253         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
254             tty_printf(_("Nothing to sign with key %08lX\n"),
255                                                   (ulong)sk_keyid[1] );
256             continue;
257         }
258         /* Ask whether we realy should sign these user id(s) */
259         tty_printf("\n");
260         show_key_with_all_names( keyblock, 1, 1, 0, 0 );
261         tty_printf("\n");
262         tty_printf(_(
263              "Are you really sure that you want to sign this key\n"
264              "with your key: \""));
265         p = get_user_id( sk_keyid, &n );
266         tty_print_string( p, n );
267         m_free(p); p = NULL;
268         tty_printf("\"\n\n");
269
270         if( !cpr_get_answer_is_yes(N_("sign_uid.okay"), _("Really sign? ")) )
271             continue;;
272         /* now we can sign the user ids */
273       reloop: /* (must use this, because we are modifing the list) */
274         primary_pk = NULL;
275         for( node=keyblock; node; node = node->next ) {
276             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
277                 primary_pk = node->pkt->pkt.public_key;
278             else if( node->pkt->pkttype == PKT_USER_ID
279                      && (node->flag & NODFLG_MARK_A) ) {
280                 PACKET *pkt;
281                 PKT_signature *sig;
282
283                 assert( primary_pk );
284                 node->flag &= ~NODFLG_MARK_A;
285                 rc = make_keysig_packet( &sig, primary_pk,
286                                                node->pkt->pkt.user_id,
287                                                NULL,
288                                                sk_rover->sk,
289                                                0x10, 0, NULL, NULL );
290                 if( rc ) {
291                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
292                     goto leave;
293                 }
294                 *ret_modified = 1; /* we changed the keyblock */
295
296                 pkt = m_alloc_clear( sizeof *pkt );
297                 pkt->pkttype = PKT_SIGNATURE;
298                 pkt->pkt.signature = sig;
299                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
300                 goto reloop;
301             }
302         }
303     } /* end loop over signators */
304
305   leave:
306     release_sk_list( sk_list );
307     return rc;
308 }
309
310
311
312
313 /****************
314  * Delete a public or secret key from a keyring.
315  */
316 int
317 delete_key( const char *username, int secret )
318 {
319     int rc = 0;
320     KBNODE keyblock = NULL;
321     KBNODE node;
322     KBPOS kbpos;
323     PKT_public_key *pk = NULL;
324     PKT_secret_key *sk = NULL;
325     u32 keyid[2];
326     int okay=0;
327     int yes;
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 batchmode\n"));
377     else if( opt.batch && opt.answer_yes )
378         okay++;
379     else if( opt.batch )
380         log_error(_("can't do that in batchmode 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         yes = cpr_get_answer_is_yes( secret? N_("delete_key.secret.okay")
401                            : N_("delete_key.okay"),
402                               _("Delete this key from the keyring? "));
403         if( !cpr_enabled() && secret && yes ) {
404             /* I think it is not required to check a passphrase; if
405              * the user is so stupid as to let others access his secret keyring
406              * (and has no backup) - it is up him to read some very
407              * basic texts about security.
408              */
409             yes = cpr_get_answer_is_yes(N_("delete_key.secret.okay"),
410                          _("This is a secret key! - really delete? "));
411         }
412         if( yes )
413             okay++;
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( cpr_get_answer_is_yes(N_("change_passwd.empty.okay"),
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, cmdTRUST, cmdPREF,
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_("pref")    , cmdPREF  , 0, N_("list preferences") },
574         { N_("passwd")  , cmdPASSWD , 1, N_("change the passphrase") },
575         { N_("trust")   , cmdTRUST , 0, N_("change the ownertrust") },
576
577     { NULL, cmdNONE } };
578     enum cmdids cmd;
579     int rc = 0;
580     KBNODE keyblock = NULL;
581     KBPOS keyblockpos;
582     KBNODE sec_keyblock = NULL;
583     KBPOS sec_keyblockpos;
584     KBNODE cur_keyblock;
585     char *answer = NULL;
586     int redisplay = 1;
587     int modified = 0;
588     int sec_modified = 0;
589     int toggle;
590
591
592     if( opt.batch ) {
593         log_error(_("can't do that in batchmode\n"));
594         goto leave;
595     }
596
597     /* first try to locate it as secret key */
598     rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
599     if( !rc ) {
600         rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
601         if( rc ) {
602             log_error("%s: secret keyblock read problem: %s\n",
603                                             username, g10_errstr(rc));
604             goto leave;
605         }
606     }
607
608     /* and now get the public key */
609     rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
610     if( rc )
611         goto leave;
612
613     if( sec_keyblock ) { /* check that they match */
614         /* FIXME: check that they both match */
615         tty_printf(_("Secret key is available.\n"));
616     }
617
618     toggle = 0;
619     cur_keyblock = keyblock;
620     for(;;) { /* main loop */
621         int i, arg_number;
622         char *p;
623
624         tty_printf("\n");
625         if( redisplay ) {
626             show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
627             tty_printf("\n");
628             redisplay = 0;
629         }
630         m_free(answer);
631         answer = cpr_get(N_("keyedit.cmd"), _("Command> "));
632         cpr_kill_prompt();
633         trim_spaces(answer);
634
635         arg_number = 0;
636         if( !*answer )
637             cmd = cmdLIST;
638         else if( isdigit( *answer ) ) {
639             cmd = cmdSELUID;
640             arg_number = atoi(answer);
641         }
642         else {
643             if( (p=strchr(answer,' ')) ) {
644                 *p++ = 0;
645                 trim_spaces(answer);
646                 trim_spaces(p);
647                 arg_number = atoi(p);
648             }
649
650             for(i=0; cmds[i].name; i++ )
651                 if( !stricmp( answer, cmds[i].name ) )
652                     break;
653             if( cmds[i].need_sk && !sec_keyblock ) {
654                 tty_printf(_("Need the secret key to to this.\n"));
655                 cmd = cmdNOP;
656             }
657             else
658                 cmd = cmds[i].id;
659         }
660         switch( cmd )  {
661           case cmdHELP:
662             for(i=0; cmds[i].name; i++ ) {
663                 if( cmds[i].need_sk && !sec_keyblock )
664                     ; /* skip if we do not have the secret key */
665                 else if( cmds[i].desc )
666                     tty_printf("%-10s %s\n", cmds[i].name, cmds[i].desc );
667             }
668             break;
669
670           case cmdQUIT:
671             if( !modified && !sec_modified )
672                 goto leave;
673             if( !cpr_get_answer_is_yes(N_("keyedit.save.okay"),
674                                         _("Save changes? ")) ) {
675                 if( cpr_enabled()
676                     || cpr_get_answer_is_yes(N_("keyedit.cancel.okay"),
677                                              _("Quit without saving? ")) )
678                     goto leave;
679                 break;
680             }
681             /* fall thru */
682           case cmdSAVE:
683             if( modified || sec_modified  ) {
684                 if( modified ) {
685                     rc = update_keyblock( &keyblockpos, keyblock );
686                     if( rc ) {
687                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
688                         break;
689                     }
690                 }
691                 if( sec_modified ) {
692                     rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
693                     if( rc ) {
694                         log_error(_("update secret failed: %s\n"),
695                                                             g10_errstr(rc) );
696                         break;
697                     }
698                 }
699                 /* FIXME: UPDATE/INVALIDATE trustdb !! */
700             }
701             else
702                 tty_printf(_("Key not changed so no update needed.\n"));
703             goto leave;
704
705           case cmdLIST:
706             redisplay = 1;
707             break;
708
709           case cmdFPR:
710             show_key_and_fingerprint( keyblock );
711             break;
712
713           case cmdSELUID:
714             if( menu_select_uid( cur_keyblock, arg_number ) )
715                 redisplay = 1;
716             break;
717
718           case cmdSELKEY:
719             if( menu_select_key( cur_keyblock, arg_number ) )
720                 redisplay = 1;
721             break;
722
723           case cmdCHECK:
724             /* we can only do this with the public key becuase the
725              * check functions can't cope with secret keys and it
726              * is questionable whether this would make sense at all */
727             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
728             break;
729
730           case cmdSIGN: /* sign (only the public key) */
731             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
732                 if( !cpr_get_answer_is_yes(N_("keyedit.sign_all.okay"),
733                                            _("Really sign all user ids? ")) ) {
734                     tty_printf(_("Hint: Select the user ids to sign\n"));
735                     break;
736                 }
737             }
738             sign_uids( keyblock, locusr, &modified );
739             break;
740
741           case cmdDEBUG:
742             dump_kbnode( cur_keyblock );
743             break;
744
745           case cmdTOGGLE:
746             toggle = !toggle;
747             cur_keyblock = toggle? sec_keyblock : keyblock;
748             redisplay = 1;
749             break;
750
751           case cmdADDUID:
752             if( menu_adduid( keyblock, sec_keyblock ) ) {
753                 redisplay = 1;
754                 sec_modified = modified = 1;
755             }
756             break;
757
758           case cmdDELUID: {
759                 int n1;
760
761                 if( !(n1=count_selected_uids(keyblock)) )
762                     tty_printf(_("You must select at least one user id.\n"));
763                 else if( count_uids(keyblock) - n1 < 1 )
764                     tty_printf(_("You can't delete the last user id!\n"));
765                 else if( cpr_get_answer_is_yes(
766                             N_("keyedit.remove.uid.okay"),
767                         n1 > 1? _("Really remove all selected user ids? ")
768                               : _("Really remove this user id? ")
769                        ) ) {
770                     menu_deluid( keyblock, sec_keyblock );
771                     redisplay = 1;
772                     modified = 1;
773                     if( sec_keyblock )
774                        sec_modified = 1;
775                 }
776             }
777             break;
778
779           case cmdADDKEY:
780             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
781                 redisplay = 1;
782                 sec_modified = modified = 1;
783             }
784             break;
785
786
787           case cmdDELKEY: {
788                 int n1;
789
790                 if( !(n1=count_selected_keys( keyblock )) )
791                     tty_printf(_("You must select at least one key.\n"));
792                 else if( sec_keyblock && !cpr_get_answer_is_yes(
793                             N_("keyedit.remove.subkey.okay"),
794                        n1 > 1?
795                         _("Do you really want to delete the selected keys? "):
796                         _("Do you really want to delete this key? ")
797                        ))
798                     ;
799                 else {
800                     menu_delkey( keyblock, sec_keyblock );
801                     redisplay = 1;
802                     modified = 1;
803                     if( sec_keyblock )
804                        sec_modified = 1;
805                 }
806             }
807             break;
808
809           case cmdPASSWD:
810             if( change_passphrase( sec_keyblock ) )
811                 sec_modified = 1;
812             break;
813
814           case cmdTRUST:
815             show_key_with_all_names( keyblock, 0, 0, 1, 0 );
816             tty_printf("\n");
817             if( edit_ownertrust( find_kbnode( keyblock,
818                       PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
819                 redisplay = 1;
820             /* we don't need to set modified here, as the trustvalues
821              * are updated immediately */
822             break;
823
824           case cmdPREF:
825             show_key_with_all_names( keyblock, 0, 0, 0, 1 );
826             break;
827
828           case cmdNOP:
829             break;
830
831           default:
832             tty_printf("\n");
833             tty_printf(_("Invalid command  (try \"help\")\n"));
834             break;
835         }
836     } /* end main loop */
837
838   leave:
839     release_kbnode( keyblock );
840     release_kbnode( sec_keyblock );
841     m_free(answer);
842 }
843
844
845 /****************
846  * show preferences of a public keyblock.
847  */
848 static void
849 show_prefs( KBNODE keyblock, PKT_user_id *uid )
850 {
851     KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
852     PKT_public_key *pk;
853     byte *p;
854     int i;
855     size_t n;
856     byte namehash[20];
857
858     if( !node )
859         return; /* is a secret keyblock */
860     pk = node->pkt->pkt.public_key;
861     if( !pk->local_id ) {
862         log_error("oops: no LID\n");
863         return;
864     }
865
866     rmd160_hash_buffer( namehash, uid->name, uid->len );
867
868     p = get_pref_data( pk->local_id, namehash, &n );
869     if( !p )
870         return;
871
872     tty_printf("    ");
873     for(i=0; i < n; i+=2 ) {
874         if( p[i] )
875             tty_printf( " %c%d", p[i] == PREFTYPE_SYM    ? 'S' :
876                                  p[i] == PREFTYPE_HASH   ? 'H' :
877                                  p[i] == PREFTYPE_COMPR  ? 'Z' : '?', p[i+1]);
878     }
879     tty_printf("\n");
880
881     m_free(p);
882 }
883
884
885 /****************
886  * Display the key a the user ids, if only_marked is true, do only
887  * so for user ids with mark A flag set and dont display the index number
888  */
889 static void
890 show_key_with_all_names( KBNODE keyblock, int only_marked,
891                          int with_fpr, int with_subkeys, int with_prefs )
892 {
893     KBNODE node;
894     int i;
895
896     /* the keys */
897     for( node = keyblock; node; node = node->next ) {
898         if( node->pkt->pkttype == PKT_PUBLIC_KEY
899             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
900             PKT_public_key *pk = node->pkt->pkt.public_key;
901             int otrust=0, trust=0;
902
903             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
904                 /* do it here, so that debug messages don't clutter the
905                  * output */
906                 trust = query_trust_info(pk);
907                 otrust = get_ownertrust_info( pk->local_id );
908             }
909
910             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s",
911                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
912                           (node->flag & NODFLG_SELKEY)? '*':' ',
913                           nbits_from_pk( pk ),
914                           pubkey_letter( pk->pubkey_algo ),
915                           (ulong)keyid_from_pk(pk,NULL),
916                           datestr_from_pk(pk),
917                           expirestr_from_pk(pk) );
918             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
919                 tty_printf(" trust: %c/%c", otrust, trust );
920                 if( with_fpr  )
921                     show_fingerprint( pk );
922             }
923             tty_printf("\n");
924         }
925         else if( node->pkt->pkttype == PKT_SECRET_KEY
926             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
927             PKT_secret_key *sk = node->pkt->pkt.secret_key;
928             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s\n",
929                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
930                           (node->flag & NODFLG_SELKEY)? '*':' ',
931                           nbits_from_sk( sk ),
932                           pubkey_letter( sk->pubkey_algo ),
933                           (ulong)keyid_from_sk(sk,NULL),
934                           datestr_from_sk(sk),
935                           expirestr_from_sk(sk) );
936         }
937     }
938     /* the user ids */
939     i = 0;
940     for( node = keyblock; node; node = node->next ) {
941         if( node->pkt->pkttype == PKT_USER_ID ) {
942             PKT_user_id *uid = node->pkt->pkt.user_id;
943             ++i;
944             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
945                 if( only_marked )
946                    tty_printf("     ");
947                 else if( node->flag & NODFLG_SELUID )
948                    tty_printf("(%d)* ", i);
949                 else
950                    tty_printf("(%d)  ", i);
951                 tty_print_string( uid->name, uid->len );
952                 tty_printf("\n");
953                 if( with_prefs )
954                     show_prefs( keyblock, uid );
955             }
956         }
957     }
958 }
959
960 static void
961 show_key_and_fingerprint( KBNODE keyblock )
962 {
963     KBNODE node;
964     PKT_public_key *pk = NULL;
965
966     for( node = keyblock; node; node = node->next ) {
967         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
968             pk = node->pkt->pkt.public_key;
969             tty_printf("pub  %4u%c/%08lX %s ",
970                           nbits_from_pk( pk ),
971                           pubkey_letter( pk->pubkey_algo ),
972                           (ulong)keyid_from_pk(pk,NULL),
973                           datestr_from_pk(pk) );
974         }
975         else if( node->pkt->pkttype == PKT_USER_ID ) {
976             PKT_user_id *uid = node->pkt->pkt.user_id;
977             tty_print_string( uid->name, uid->len );
978             break;
979         }
980     }
981     tty_printf("\n");
982     if( pk )
983         show_fingerprint( pk );
984 }
985
986
987 static void
988 show_fingerprint( PKT_public_key *pk )
989 {
990     byte *array, *p;
991     size_t i, n;
992
993     p = array = fingerprint_from_pk( pk, NULL, &n );
994     tty_printf("             Fingerprint:");
995     if( n == 20 ) {
996         for(i=0; i < n ; i++, i++, p += 2 ) {
997             if( i == 10 )
998                 tty_printf(" ");
999             tty_printf(" %02X%02X", *p, p[1] );
1000         }
1001     }
1002     else {
1003         for(i=0; i < n ; i++, p++ ) {
1004             if( i && !(i%8) )
1005                 tty_printf(" ");
1006             tty_printf(" %02X", *p );
1007         }
1008     }
1009     tty_printf("\n");
1010     m_free(array);
1011 }
1012
1013
1014 /****************
1015  * Ask for a new user id , do the selfsignature and put it into
1016  * both keyblocks.
1017  * Return true if there is a new user id
1018  */
1019 static int
1020 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1021 {
1022     PKT_user_id *uid;
1023     PKT_public_key *pk=NULL;
1024     PKT_secret_key *sk=NULL;
1025     PKT_signature *sig=NULL;
1026     PACKET *pkt;
1027     KBNODE node;
1028     KBNODE pub_where=NULL, sec_where=NULL;
1029     int rc;
1030
1031     uid = generate_user_id();
1032     if( !uid )
1033         return 0;
1034
1035     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1036         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1037             pk = node->pkt->pkt.public_key;
1038         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1039             break;
1040     }
1041     if( !node ) /* no subkey */
1042         pub_where = NULL;
1043     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1044         if( node->pkt->pkttype == PKT_SECRET_KEY )
1045             sk = node->pkt->pkt.secret_key;
1046         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1047             break;
1048     }
1049     if( !node ) /* no subkey */
1050         sec_where = NULL;
1051     assert(pk && sk );
1052
1053     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
1054                              keygen_add_std_prefs, sk );
1055     if( rc ) {
1056         log_error("signing failed: %s\n", g10_errstr(rc) );
1057         free_user_id(uid);
1058         return 0;
1059     }
1060
1061     /* insert/append to secret keyblock */
1062     pkt = m_alloc_clear( sizeof *pkt );
1063     pkt->pkttype = PKT_USER_ID;
1064     pkt->pkt.user_id = copy_user_id(NULL, uid);
1065     node = new_kbnode(pkt);
1066     if( sec_where )
1067         insert_kbnode( sec_where, node, 0 );
1068     else
1069         add_kbnode( sec_keyblock, node );
1070     pkt = m_alloc_clear( sizeof *pkt );
1071     pkt->pkttype = PKT_SIGNATURE;
1072     pkt->pkt.signature = copy_signature(NULL, sig);
1073     if( sec_where )
1074         insert_kbnode( node, new_kbnode(pkt), 0 );
1075     else
1076         add_kbnode( sec_keyblock, new_kbnode(pkt) );
1077     /* insert/append to public keyblock */
1078     pkt = m_alloc_clear( sizeof *pkt );
1079     pkt->pkttype = PKT_USER_ID;
1080     pkt->pkt.user_id = uid;
1081     node = new_kbnode(pkt);
1082     if( pub_where )
1083         insert_kbnode( pub_where, node, 0 );
1084     else
1085         add_kbnode( pub_keyblock, node );
1086     pkt = m_alloc_clear( sizeof *pkt );
1087     pkt->pkttype = PKT_SIGNATURE;
1088     pkt->pkt.signature = copy_signature(NULL, sig);
1089     if( pub_where )
1090         insert_kbnode( node, new_kbnode(pkt), 0 );
1091     else
1092         add_kbnode( pub_keyblock, new_kbnode(pkt) );
1093     return 1;
1094 }
1095
1096
1097 /****************
1098  * Remove all selceted userids from the keyrings
1099  */
1100 static void
1101 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1102 {
1103     KBNODE node;
1104     int selected=0;
1105
1106     for( node = pub_keyblock; node; node = node->next ) {
1107         if( node->pkt->pkttype == PKT_USER_ID ) {
1108             selected = node->flag & NODFLG_SELUID;
1109             if( selected ) {
1110                 delete_kbnode( node );
1111                 if( sec_keyblock ) {
1112                     KBNODE snode;
1113                     int s_selected = 0;
1114                     PKT_user_id *uid = node->pkt->pkt.user_id;
1115                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1116                         if( snode->pkt->pkttype == PKT_USER_ID ) {
1117                             PKT_user_id *suid = snode->pkt->pkt.user_id;
1118
1119                             s_selected =
1120                                 (uid->len == suid->len
1121                                  && !memcmp( uid->name, suid->name, uid->len));
1122                             if( s_selected )
1123                                 delete_kbnode( snode );
1124                         }
1125                         else if( s_selected
1126                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1127                             delete_kbnode( snode );
1128                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1129                             s_selected = 0;
1130                     }
1131                 }
1132             }
1133         }
1134         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1135             delete_kbnode( node );
1136         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1137             selected = 0;
1138     }
1139     commit_kbnode( &pub_keyblock );
1140     if( sec_keyblock )
1141         commit_kbnode( &sec_keyblock );
1142 }
1143
1144
1145 /****************
1146  * Remove some of the secondary keys
1147  */
1148 static void
1149 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1150 {
1151     KBNODE node;
1152     int selected=0;
1153
1154     for( node = pub_keyblock; node; node = node->next ) {
1155         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1156             selected = node->flag & NODFLG_SELKEY;
1157             if( selected ) {
1158                 delete_kbnode( node );
1159                 if( sec_keyblock ) {
1160                     KBNODE snode;
1161                     int s_selected = 0;
1162                     u32 ki[2];
1163
1164                     keyid_from_pk( node->pkt->pkt.public_key, ki );
1165                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1166                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1167                             u32 ki2[2];
1168
1169                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1170                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1171                             if( s_selected )
1172                                 delete_kbnode( snode );
1173                         }
1174                         else if( s_selected
1175                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1176                             delete_kbnode( snode );
1177                         else
1178                             s_selected = 0;
1179                     }
1180                 }
1181             }
1182         }
1183         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1184             delete_kbnode( node );
1185         else
1186             selected = 0;
1187     }
1188     commit_kbnode( &pub_keyblock );
1189     if( sec_keyblock )
1190         commit_kbnode( &sec_keyblock );
1191 }
1192
1193
1194 /****************
1195  * Select one user id or remove all selection if index is 0.
1196  * Returns: True if the selection changed;
1197  */
1198 static int
1199 menu_select_uid( KBNODE keyblock, int index )
1200 {
1201     KBNODE node;
1202     int i;
1203
1204     /* first check that the index is valid */
1205     if( index ) {
1206         for( i=0, node = keyblock; node; node = node->next ) {
1207             if( node->pkt->pkttype == PKT_USER_ID ) {
1208                 if( ++i == index )
1209                     break;
1210             }
1211         }
1212         if( !node ) {
1213             tty_printf(_("No user id with index %d\n"), index );
1214             return 0;
1215         }
1216     }
1217     else { /* reset all */
1218         for( i=0, node = keyblock; node; node = node->next ) {
1219             if( node->pkt->pkttype == PKT_USER_ID )
1220                 node->flag &= ~NODFLG_SELUID;
1221         }
1222         return 1;
1223     }
1224     /* and toggle the new index */
1225     for( i=0, node = keyblock; node; node = node->next ) {
1226         if( node->pkt->pkttype == PKT_USER_ID ) {
1227             if( ++i == index )
1228                 if( (node->flag & NODFLG_SELUID) )
1229                     node->flag &= ~NODFLG_SELUID;
1230                 else
1231                     node->flag |= NODFLG_SELUID;
1232         }
1233     }
1234
1235     return 1;
1236 }
1237
1238 /****************
1239  * Select secondary keys
1240  * Returns: True if the selection changed;
1241  */
1242 static int
1243 menu_select_key( KBNODE keyblock, int index )
1244 {
1245     KBNODE node;
1246     int i;
1247
1248     /* first check that the index is valid */
1249     if( index ) {
1250         for( i=0, node = keyblock; node; node = node->next ) {
1251             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1252                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1253                 if( ++i == index )
1254                     break;
1255             }
1256         }
1257         if( !node ) {
1258             tty_printf(_("No secondary key with index %d\n"), index );
1259             return 0;
1260         }
1261     }
1262     else { /* reset all */
1263         for( i=0, node = keyblock; node; node = node->next ) {
1264             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1265                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1266                 node->flag &= ~NODFLG_SELKEY;
1267         }
1268         return 1;
1269     }
1270     /* and set the new index */
1271     for( i=0, node = keyblock; node; node = node->next ) {
1272         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1273             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1274             if( ++i == index )
1275                 if( (node->flag & NODFLG_SELKEY) )
1276                     node->flag &= ~NODFLG_SELKEY;
1277                 else
1278                     node->flag |= NODFLG_SELKEY;
1279         }
1280     }
1281
1282     return 1;
1283 }
1284
1285
1286 static int
1287 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1288 {
1289     KBNODE node;
1290     int i=0;
1291
1292     for( node = keyblock; node; node = node->next )
1293         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1294             i++;
1295     return i;
1296 }
1297
1298 static int
1299 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1300 {
1301     KBNODE node;
1302     int i=0;
1303
1304     for( node = keyblock; node; node = node->next )
1305         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1306               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1307             && (node->flag & flag) )
1308             i++;
1309     return i;
1310 }
1311
1312 static int
1313 count_uids( KBNODE keyblock )
1314 {
1315     KBNODE node;
1316     int i=0;
1317
1318     for( node = keyblock; node; node = node->next )
1319         if( node->pkt->pkttype == PKT_USER_ID )
1320             i++;
1321     return i;
1322 }
1323
1324
1325 /****************
1326  * Returns true if there is at least one selected user id
1327  */
1328 static int
1329 count_selected_uids( KBNODE keyblock )
1330 {
1331     return count_uids_with_flag( keyblock, NODFLG_SELUID);
1332 }
1333
1334 static int
1335 count_selected_keys( KBNODE keyblock )
1336 {
1337     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
1338 }
1339