ready for a new 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         tty_printf("\"\n\n");
268         m_free(p);
269         p = cpr_get(N_("sign_uid.okay"), _("Really sign? "));
270         cpr_kill_prompt();
271         if( !answer_is_yes(p) ) {
272             m_free(p);
273             continue; /* No */
274         }
275         m_free(p);
276         /* now we can sign the user ids */
277       reloop: /* (must use this, because we are modifing the list) */
278         primary_pk = NULL;
279         for( node=keyblock; node; node = node->next ) {
280             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
281                 primary_pk = node->pkt->pkt.public_key;
282             else if( node->pkt->pkttype == PKT_USER_ID
283                      && (node->flag & NODFLG_MARK_A) ) {
284                 PACKET *pkt;
285                 PKT_signature *sig;
286
287                 assert( primary_pk );
288                 node->flag &= ~NODFLG_MARK_A;
289                 rc = make_keysig_packet( &sig, primary_pk,
290                                                node->pkt->pkt.user_id,
291                                                NULL,
292                                                sk_rover->sk,
293                                                0x10, 0, NULL, NULL );
294                 if( rc ) {
295                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
296                     goto leave;
297                 }
298                 *ret_modified = 1; /* we changed the keyblock */
299
300                 pkt = m_alloc_clear( sizeof *pkt );
301                 pkt->pkttype = PKT_SIGNATURE;
302                 pkt->pkt.signature = sig;
303                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
304                 goto reloop;
305             }
306         }
307     } /* end loop over signators */
308
309   leave:
310     release_sk_list( sk_list );
311     return rc;
312 }
313
314
315
316
317 /****************
318  * Delete a public or secret key from a keyring.
319  */
320 int
321 delete_key( const char *username, int secret )
322 {
323     int rc = 0;
324     KBNODE keyblock = NULL;
325     KBNODE node;
326     KBPOS kbpos;
327     PKT_public_key *pk = NULL;
328     PKT_secret_key *sk = NULL;
329     u32 keyid[2];
330     int okay=0;
331
332     /* search the userid */
333     rc = secret? find_secret_keyblock_byname( &kbpos, username )
334                : find_keyblock_byname( &kbpos, username );
335     if( rc ) {
336         log_error(_("%s: user not found\n"), username );
337         goto leave;
338     }
339
340     /* read the keyblock */
341     rc = read_keyblock( &kbpos, &keyblock );
342     if( rc ) {
343         log_error("%s: read problem: %s\n", username, g10_errstr(rc) );
344         goto leave;
345     }
346
347     /* get the keyid from the keyblock */
348     node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
349     if( !node ) {
350         log_error("Oops; key not found anymore!\n");
351         rc = G10ERR_GENERAL;
352         goto leave;
353     }
354
355     if( secret ) {
356         sk = node->pkt->pkt.secret_key;
357         keyid_from_sk( sk, keyid );
358     }
359     else {
360         pk = node->pkt->pkt.public_key;
361         keyid_from_pk( pk, keyid );
362         rc = seckey_available( keyid );
363         if( !rc ) {
364             log_error(_(
365             "there is a secret key for this public key!\n"));
366             log_info(_(
367             "use option \"--delete-secret-key\" to delete it first.\n"));
368             rc = -1;
369         }
370         else if( rc != G10ERR_NO_SECKEY )
371             log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
372         else
373             rc = 0;
374     }
375
376     if( rc )
377         rc = 0;
378     else if( opt.batch && secret )
379         log_error(_("can't do that in batch-mode\n"));
380     else if( opt.batch && opt.answer_yes )
381         okay++;
382     else if( opt.batch )
383         log_error(_("can't do that in batch-mode without \"--yes\"\n"));
384     else {
385         char *p;
386         size_t n;
387
388         if( secret )
389             tty_printf("sec  %4u%c/%08lX %s   ",
390                       nbits_from_sk( sk ),
391                       pubkey_letter( sk->pubkey_algo ),
392                       keyid[1], datestr_from_sk(sk) );
393         else
394             tty_printf("pub  %4u%c/%08lX %s   ",
395                       nbits_from_pk( pk ),
396                       pubkey_letter( pk->pubkey_algo ),
397                       keyid[1], datestr_from_pk(pk) );
398         p = get_user_id( keyid, &n );
399         tty_print_string( p, n );
400         m_free(p);
401         tty_printf("\n\n");
402
403         p = cpr_get( secret? N_("delete_key.secret.okay")
404                            : N_("delete_key.okay"),
405                               _("Delete this key from the keyring? "));
406         cpr_kill_prompt();
407         if( !cpr_enabled() && secret && answer_is_yes(p)) {
408             /* I think it is not required to check a passphrase; if
409              * the user is so stupid as to let others access his secret keyring
410              * (and has no backup) - it is up him to read some very
411              * basic texts about security.
412              */
413             m_free(p);
414             p = cpr_get(N_("delete_key.secret.okay"),
415                          _("This is a secret key! - really delete? "));
416         }
417         if( answer_is_yes(p) )
418             okay++;
419         m_free(p);
420     }
421
422
423     if( okay ) {
424         rc = delete_keyblock( &kbpos );
425         if( rc ) {
426             log_error("delete_keyblock failed: %s\n", g10_errstr(rc) );
427             goto leave;
428         }
429     }
430
431   leave:
432     release_kbnode( keyblock );
433     return rc;
434 }
435
436
437 /****************
438  * Change the passphrase of the primary and all secondary keys.
439  * We use only one passphrase for all keys.
440  */
441 static int
442 change_passphrase( KBNODE keyblock )
443 {
444     int rc = 0;
445     int changed=0;
446     KBNODE node;
447     PKT_secret_key *sk;
448     char *passphrase = NULL;
449
450     node = find_kbnode( keyblock, PKT_SECRET_KEY );
451     if( !node ) {
452         log_error("Oops; secret key not found anymore!\n");
453         goto leave;
454     }
455     sk = node->pkt->pkt.secret_key;
456
457     switch( is_secret_key_protected( sk ) ) {
458       case -1:
459         rc = G10ERR_PUBKEY_ALGO;
460         break;
461       case 0:
462         tty_printf(_("This key is not protected.\n"));
463         break;
464       default:
465         tty_printf(_("Key is protected.\n"));
466         rc = check_secret_key( sk );
467         if( !rc )
468             passphrase = get_last_passphrase();
469         break;
470     }
471
472     /* unprotect all subkeys (use the supplied passphrase or ask)*/
473     for(node=keyblock; !rc && node; node = node->next ) {
474         if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
475             PKT_secret_key *subsk = node->pkt->pkt.secret_key;
476             set_next_passphrase( passphrase );
477             rc = check_secret_key( subsk );
478         }
479     }
480
481     if( rc )
482         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
483     else {
484         DEK *dek = NULL;
485         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
486
487         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
488
489         set_next_passphrase( NULL );
490         for(;;) {
491             s2k->mode = 1;
492             s2k->hash_algo = DIGEST_ALGO_RMD160;
493             dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 );
494             if( !dek ) {
495                 tty_printf(_("passphrase not correctly repeated; try again.\n"));
496             }
497             else if( !dek->keylen ) {
498                 rc = 0;
499                 tty_printf(_( "You don't want a passphrase -"
500                             " this is probably a *bad* idea!\n\n"));
501                 if( cpr_get_answer_is_yes(N_("change_passwd.empty.okay"),
502                                _("Do you really want to do this? ")))
503                     changed++;
504                 break;
505             }
506             else { /* okay */
507                 sk->protect.algo = dek->algo;
508                 sk->protect.s2k = *s2k;
509                 rc = protect_secret_key( sk, dek );
510                 for(node=keyblock; !rc && node; node = node->next ) {
511                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
512                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
513                         subsk->protect.algo = dek->algo;
514                         subsk->protect.s2k = *s2k;
515                         rc = protect_secret_key( subsk, dek );
516                     }
517                 }
518                 if( rc )
519                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
520                 else
521                     changed++;
522                 break;
523             }
524         }
525         m_free(s2k);
526         m_free(dek);
527     }
528
529   leave:
530     m_free( passphrase );
531     set_next_passphrase( NULL );
532     return changed && !rc;
533 }
534
535
536
537
538 /****************
539  * Menu driven key editor
540  *
541  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
542  */
543
544 void
545 keyedit_menu( const char *username, STRLIST locusr )
546 {
547     enum cmdids { cmdNONE = 0,
548            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
549            cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
550            cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
551            cmdNOP };
552     static struct { const char *name;
553                     enum cmdids id;
554                     int need_sk;
555                     const char *desc;
556                   } cmds[] = {
557         { N_("quit")    , cmdQUIT   , 0, N_("quit this menu") },
558         { N_("q")       , cmdQUIT   , 0, NULL   },
559         { N_("save")    , cmdSAVE   , 0, N_("save and quit") },
560         { N_("help")    , cmdHELP   , 0, N_("show this help") },
561         {    "?"        , cmdHELP   , 0, NULL   },
562         { N_("fpr")     , cmdFPR    , 0, N_("show fingerprint") },
563         { N_("list")    , cmdLIST   , 0, N_("list key and user ids") },
564         { N_("l")       , cmdLIST   , 0, NULL   },
565         { N_("uid")     , cmdSELUID , 0, N_("select user id N") },
566         { N_("key")     , cmdSELKEY , 0, N_("select secondary key N") },
567         { N_("check")   , cmdCHECK  , 0, N_("list signatures") },
568         { N_("c")       , cmdCHECK  , 0, NULL },
569         { N_("sign")    , cmdSIGN   , 0, N_("sign the key") },
570         { N_("s")       , cmdSIGN   , 0, NULL },
571         { N_("debug")   , cmdDEBUG  , 0, NULL },
572         { N_("adduid")  , cmdADDUID , 1, N_("add a user id") },
573         { N_("deluid")  , cmdDELUID , 0, N_("delete user id") },
574         { N_("addkey")  , cmdADDKEY , 1, N_("add a secondary key") },
575         { N_("delkey")  , cmdDELKEY , 0, N_("delete a secondary key") },
576         { N_("toggle")  , cmdTOGGLE , 1, N_("toggle between secret "
577                                             "and public key listing") },
578         { N_("t"     )  , cmdTOGGLE , 1, NULL },
579         { N_("pref")    , cmdPREF  , 0, N_("list preferences") },
580         { N_("passwd")  , cmdPASSWD , 1, N_("change the passphrase") },
581         { N_("trust")   , cmdTRUST , 0, N_("change the ownertrust") },
582
583     { NULL, cmdNONE } };
584     enum cmdids cmd;
585     int rc = 0;
586     KBNODE keyblock = NULL;
587     KBPOS keyblockpos;
588     KBNODE sec_keyblock = NULL;
589     KBPOS sec_keyblockpos;
590     KBNODE cur_keyblock;
591     char *answer = NULL;
592     int redisplay = 1;
593     int modified = 0;
594     int sec_modified = 0;
595     int toggle;
596
597
598     if( opt.batch ) {
599         log_error(_("can't do that in batch-mode\n"));
600         goto leave;
601     }
602
603     /* first try to locate it as secret key */
604     rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
605     if( !rc ) {
606         rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
607         if( rc ) {
608             log_error("%s: secret keyblock read problem: %s\n",
609                                             username, g10_errstr(rc));
610             goto leave;
611         }
612     }
613
614     /* and now get the public key */
615     rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
616     if( rc )
617         goto leave;
618
619     if( sec_keyblock ) { /* check that they match */
620         /* FIXME: check that they both match */
621         tty_printf(_("Secret key is available.\n"));
622     }
623
624     toggle = 0;
625     cur_keyblock = keyblock;
626     for(;;) { /* main loop */
627         int i, arg_number;
628         char *p;
629
630         tty_printf("\n");
631         if( redisplay ) {
632             show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
633             tty_printf("\n");
634             redisplay = 0;
635         }
636         m_free(answer);
637         answer = cpr_get(N_("keyedit.cmd"), _("Command> "));
638         cpr_kill_prompt();
639         trim_spaces(answer);
640
641         arg_number = 0;
642         if( !*answer )
643             cmd = cmdLIST;
644         else if( isdigit( *answer ) ) {
645             cmd = cmdSELUID;
646             arg_number = atoi(answer);
647         }
648         else {
649             if( (p=strchr(answer,' ')) ) {
650                 *p++ = 0;
651                 trim_spaces(answer);
652                 trim_spaces(p);
653                 arg_number = atoi(p);
654             }
655
656             for(i=0; cmds[i].name; i++ )
657                 if( !stricmp( answer, cmds[i].name ) )
658                     break;
659             if( cmds[i].need_sk && !sec_keyblock ) {
660                 tty_printf(_("Need the secret key to to this.\n"));
661                 cmd = cmdNOP;
662             }
663             else
664                 cmd = cmds[i].id;
665         }
666         switch( cmd )  {
667           case cmdHELP:
668             for(i=0; cmds[i].name; i++ ) {
669                 if( cmds[i].need_sk && !sec_keyblock )
670                     ; /* skip if we do not have the secret key */
671                 else if( cmds[i].desc )
672                     tty_printf("%-10s %s\n", cmds[i].name, cmds[i].desc );
673             }
674             break;
675
676           case cmdQUIT:
677             if( !modified && !sec_modified )
678                 goto leave;
679             if( !cpr_get_answer_is_yes(N_("keyedit.save.okay"),
680                                         _("Save changes? ")) ) {
681                 if( cpr_enabled()
682                     || cpr_get_answer_is_yes(N_("keyedit.cancel.okay"),
683                                              _("Quit without saving? ")) )
684                     goto leave;
685                 break;
686             }
687             /* fall thru */
688           case cmdSAVE:
689             if( modified || sec_modified  ) {
690                 if( modified ) {
691                     rc = update_keyblock( &keyblockpos, keyblock );
692                     if( rc ) {
693                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
694                         break;
695                     }
696                 }
697                 if( sec_modified ) {
698                     rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
699                     if( rc ) {
700                         log_error(_("update secret failed: %s\n"),
701                                                             g10_errstr(rc) );
702                         break;
703                     }
704                 }
705                 /* FIXME: UPDATE/INVALIDATE trustdb !! */
706             }
707             else
708                 tty_printf(_("Key not changed so no update needed.\n"));
709             goto leave;
710
711           case cmdLIST:
712             redisplay = 1;
713             break;
714
715           case cmdFPR:
716             show_key_and_fingerprint( keyblock );
717             break;
718
719           case cmdSELUID:
720             if( menu_select_uid( cur_keyblock, arg_number ) )
721                 redisplay = 1;
722             break;
723
724           case cmdSELKEY:
725             if( menu_select_key( cur_keyblock, arg_number ) )
726                 redisplay = 1;
727             break;
728
729           case cmdCHECK:
730             /* we can only do this with the public key becuase the
731              * check functions can't cope with secret keys and it
732              * is questionable whether this would make sense at all */
733             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
734             break;
735
736           case cmdSIGN: /* sign (only the public key) */
737             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
738                 if( !cpr_get_answer_is_yes(N_("keyedit.signall.okay"),
739                                            _("Really sign all user ids? ")) ) {
740                     tty_printf(_("Hint: Select the user ids to sign\n"));
741                     break;
742                 }
743             }
744             sign_uids( keyblock, locusr, &modified );
745             break;
746
747           case cmdDEBUG:
748             dump_kbnode( cur_keyblock );
749             break;
750
751           case cmdTOGGLE:
752             toggle = !toggle;
753             cur_keyblock = toggle? sec_keyblock : keyblock;
754             redisplay = 1;
755             break;
756
757           case cmdADDUID:
758             if( menu_adduid( keyblock, sec_keyblock ) ) {
759                 redisplay = 1;
760                 sec_modified = modified = 1;
761             }
762             break;
763
764           case cmdDELUID: {
765                 int n1;
766
767                 if( !(n1=count_selected_uids(keyblock)) )
768                     tty_printf(_("You must select at least one user id.\n"));
769                 else if( count_uids(keyblock) - n1 < 1 )
770                     tty_printf(_("You can't delete the last user id!\n"));
771                 else if( cpr_get_answer_is_yes(
772                             N_("keyedit.remove.uid.okay"),
773                         n1 > 1? _("Really remove all selected user ids? ")
774                               : _("Really remove this user id? ")
775                        ) ) {
776                     menu_deluid( keyblock, sec_keyblock );
777                     redisplay = 1;
778                     modified = 1;
779                     if( sec_keyblock )
780                        sec_modified = 1;
781                 }
782             }
783             break;
784
785           case cmdADDKEY:
786             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
787                 redisplay = 1;
788                 sec_modified = modified = 1;
789             }
790             break;
791
792
793           case cmdDELKEY: {
794                 int n1;
795
796                 if( !(n1=count_selected_keys( keyblock )) )
797                     tty_printf(_("You must select at least one key.\n"));
798                 else if( sec_keyblock && !cpr_get_answer_is_yes(
799                             N_("keyedit.remove.subkey.okay"),
800                        n1 > 1?
801                         _("Do you really want to delete the selected keys? "):
802                         _("Do you really want to delete this key? ")
803                        ))
804                     ;
805                 else {
806                     menu_delkey( keyblock, sec_keyblock );
807                     redisplay = 1;
808                     modified = 1;
809                     if( sec_keyblock )
810                        sec_modified = 1;
811                 }
812             }
813             break;
814
815           case cmdPASSWD:
816             if( change_passphrase( sec_keyblock ) )
817                 sec_modified = 1;
818             break;
819
820           case cmdTRUST:
821             show_key_with_all_names( keyblock, 0, 0, 1, 0 );
822             tty_printf("\n");
823             if( edit_ownertrust( find_kbnode( keyblock,
824                       PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
825                 redisplay = 1;
826             /* we don't need to set modified here, as the trustvalues
827              * are updated immediately */
828             break;
829
830           case cmdPREF:
831             show_key_with_all_names( keyblock, 0, 0, 0, 1 );
832             break;
833
834           case cmdNOP:
835             break;
836
837           default:
838             tty_printf("\n");
839             tty_printf(_("Invalid command  (try \"help\")\n"));
840             break;
841         }
842     } /* end main loop */
843
844   leave:
845     release_kbnode( keyblock );
846     release_kbnode( sec_keyblock );
847     m_free(answer);
848 }
849
850
851 /****************
852  * show preferences of a public keyblock.
853  */
854 static void
855 show_prefs( KBNODE keyblock, PKT_user_id *uid )
856 {
857     KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
858     PKT_public_key *pk;
859     byte *p;
860     int i;
861     size_t n;
862     byte namehash[20];
863
864     if( !node )
865         return; /* is a secret keyblock */
866     pk = node->pkt->pkt.public_key;
867     if( !pk->local_id ) {
868         log_error("oops: no LID\n");
869         return;
870     }
871
872     rmd160_hash_buffer( namehash, uid->name, uid->len );
873
874     p = get_pref_data( pk->local_id, namehash, &n );
875     if( !p )
876         return;
877
878     tty_printf("    ");
879     for(i=0; i < n; i+=2 ) {
880         if( p[i] )
881             tty_printf( " %c%d", p[i] == PREFTYPE_SYM    ? 'S' :
882                                  p[i] == PREFTYPE_HASH   ? 'H' :
883                                  p[i] == PREFTYPE_COMPR  ? 'Z' : '?', p[i+1]);
884     }
885     tty_printf("\n");
886
887     m_free(p);
888 }
889
890
891 /****************
892  * Display the key a the user ids, if only_marked is true, do only
893  * so for user ids with mark A flag set and dont display the index number
894  */
895 static void
896 show_key_with_all_names( KBNODE keyblock, int only_marked,
897                          int with_fpr, int with_subkeys, int with_prefs )
898 {
899     KBNODE node;
900     int i;
901
902     /* the keys */
903     for( node = keyblock; node; node = node->next ) {
904         if( node->pkt->pkttype == PKT_PUBLIC_KEY
905             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
906             PKT_public_key *pk = node->pkt->pkt.public_key;
907             int otrust=0, trust=0;
908
909             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
910                 /* do it here, so that debug messages don't clutter the
911                  * output */
912                 trust = query_trust_info(pk);
913                 otrust = get_ownertrust_info( pk->local_id );
914             }
915
916             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s",
917                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
918                           (node->flag & NODFLG_SELKEY)? '*':' ',
919                           nbits_from_pk( pk ),
920                           pubkey_letter( pk->pubkey_algo ),
921                           (ulong)keyid_from_pk(pk,NULL),
922                           datestr_from_pk(pk),
923                           expirestr_from_pk(pk) );
924             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
925                 tty_printf(" trust: %c/%c", otrust, trust );
926                 if( with_fpr  )
927                     show_fingerprint( pk );
928             }
929             tty_printf("\n");
930         }
931         else if( node->pkt->pkttype == PKT_SECRET_KEY
932             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
933             PKT_secret_key *sk = node->pkt->pkt.secret_key;
934             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s\n",
935                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
936                           (node->flag & NODFLG_SELKEY)? '*':' ',
937                           nbits_from_sk( sk ),
938                           pubkey_letter( sk->pubkey_algo ),
939                           (ulong)keyid_from_sk(sk,NULL),
940                           datestr_from_sk(sk),
941                           expirestr_from_sk(sk) );
942         }
943     }
944     /* the user ids */
945     i = 0;
946     for( node = keyblock; node; node = node->next ) {
947         if( node->pkt->pkttype == PKT_USER_ID ) {
948             PKT_user_id *uid = node->pkt->pkt.user_id;
949             ++i;
950             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
951                 if( only_marked )
952                    tty_printf("     ");
953                 else if( node->flag & NODFLG_SELUID )
954                    tty_printf("(%d)* ", i);
955                 else
956                    tty_printf("(%d)  ", i);
957                 tty_print_string( uid->name, uid->len );
958                 tty_printf("\n");
959                 if( with_prefs )
960                     show_prefs( keyblock, uid );
961             }
962         }
963     }
964 }
965
966 static void
967 show_key_and_fingerprint( KBNODE keyblock )
968 {
969     KBNODE node;
970     PKT_public_key *pk = NULL;
971
972     for( node = keyblock; node; node = node->next ) {
973         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
974             pk = node->pkt->pkt.public_key;
975             tty_printf("pub  %4u%c/%08lX %s ",
976                           nbits_from_pk( pk ),
977                           pubkey_letter( pk->pubkey_algo ),
978                           (ulong)keyid_from_pk(pk,NULL),
979                           datestr_from_pk(pk) );
980         }
981         else if( node->pkt->pkttype == PKT_USER_ID ) {
982             PKT_user_id *uid = node->pkt->pkt.user_id;
983             tty_print_string( uid->name, uid->len );
984             break;
985         }
986     }
987     tty_printf("\n");
988     if( pk )
989         show_fingerprint( pk );
990 }
991
992
993 static void
994 show_fingerprint( PKT_public_key *pk )
995 {
996     byte *array, *p;
997     size_t i, n;
998
999     p = array = fingerprint_from_pk( pk, NULL, &n );
1000     tty_printf("             Fingerprint:");
1001     if( n == 20 ) {
1002         for(i=0; i < n ; i++, i++, p += 2 ) {
1003             if( i == 10 )
1004                 tty_printf(" ");
1005             tty_printf(" %02X%02X", *p, p[1] );
1006         }
1007     }
1008     else {
1009         for(i=0; i < n ; i++, p++ ) {
1010             if( i && !(i%8) )
1011                 tty_printf(" ");
1012             tty_printf(" %02X", *p );
1013         }
1014     }
1015     tty_printf("\n");
1016     m_free(array);
1017 }
1018
1019
1020 /****************
1021  * Ask for a new user id , do the selfsignature and put it into
1022  * both keyblocks.
1023  * Return true if there is a new user id
1024  */
1025 static int
1026 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1027 {
1028     PKT_user_id *uid;
1029     PKT_public_key *pk=NULL;
1030     PKT_secret_key *sk=NULL;
1031     PKT_signature *sig=NULL;
1032     PACKET *pkt;
1033     KBNODE node;
1034     KBNODE pub_where=NULL, sec_where=NULL;
1035     int rc;
1036
1037     uid = generate_user_id();
1038     if( !uid )
1039         return 0;
1040
1041     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1042         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1043             pk = node->pkt->pkt.public_key;
1044         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1045             break;
1046     }
1047     if( !node ) /* no subkey */
1048         pub_where = NULL;
1049     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1050         if( node->pkt->pkttype == PKT_SECRET_KEY )
1051             sk = node->pkt->pkt.secret_key;
1052         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1053             break;
1054     }
1055     if( !node ) /* no subkey */
1056         sec_where = NULL;
1057     assert(pk && sk );
1058
1059     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
1060                              keygen_add_std_prefs, sk );
1061     if( rc ) {
1062         log_error("signing failed: %s\n", g10_errstr(rc) );
1063         free_user_id(uid);
1064         return 0;
1065     }
1066
1067     /* insert/append to secret keyblock */
1068     pkt = m_alloc_clear( sizeof *pkt );
1069     pkt->pkttype = PKT_USER_ID;
1070     pkt->pkt.user_id = copy_user_id(NULL, uid);
1071     node = new_kbnode(pkt);
1072     if( sec_where )
1073         insert_kbnode( sec_where, node, 0 );
1074     else
1075         add_kbnode( sec_keyblock, node );
1076     pkt = m_alloc_clear( sizeof *pkt );
1077     pkt->pkttype = PKT_SIGNATURE;
1078     pkt->pkt.signature = copy_signature(NULL, sig);
1079     if( sec_where )
1080         insert_kbnode( node, new_kbnode(pkt), 0 );
1081     else
1082         add_kbnode( sec_keyblock, new_kbnode(pkt) );
1083     /* insert/append to public keyblock */
1084     pkt = m_alloc_clear( sizeof *pkt );
1085     pkt->pkttype = PKT_USER_ID;
1086     pkt->pkt.user_id = uid;
1087     node = new_kbnode(pkt);
1088     if( pub_where )
1089         insert_kbnode( pub_where, node, 0 );
1090     else
1091         add_kbnode( pub_keyblock, node );
1092     pkt = m_alloc_clear( sizeof *pkt );
1093     pkt->pkttype = PKT_SIGNATURE;
1094     pkt->pkt.signature = copy_signature(NULL, sig);
1095     if( pub_where )
1096         insert_kbnode( node, new_kbnode(pkt), 0 );
1097     else
1098         add_kbnode( pub_keyblock, new_kbnode(pkt) );
1099     return 1;
1100 }
1101
1102
1103 /****************
1104  * Remove all selceted userids from the keyrings
1105  */
1106 static void
1107 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1108 {
1109     KBNODE node;
1110     int selected=0;
1111
1112     for( node = pub_keyblock; node; node = node->next ) {
1113         if( node->pkt->pkttype == PKT_USER_ID ) {
1114             selected = node->flag & NODFLG_SELUID;
1115             if( selected ) {
1116                 delete_kbnode( node );
1117                 if( sec_keyblock ) {
1118                     KBNODE snode;
1119                     int s_selected = 0;
1120                     PKT_user_id *uid = node->pkt->pkt.user_id;
1121                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1122                         if( snode->pkt->pkttype == PKT_USER_ID ) {
1123                             PKT_user_id *suid = snode->pkt->pkt.user_id;
1124
1125                             s_selected =
1126                                 (uid->len == suid->len
1127                                  && !memcmp( uid->name, suid->name, uid->len));
1128                             if( s_selected )
1129                                 delete_kbnode( snode );
1130                         }
1131                         else if( s_selected
1132                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1133                             delete_kbnode( snode );
1134                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1135                             s_selected = 0;
1136                     }
1137                 }
1138             }
1139         }
1140         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1141             delete_kbnode( node );
1142         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1143             selected = 0;
1144     }
1145     commit_kbnode( &pub_keyblock );
1146     if( sec_keyblock )
1147         commit_kbnode( &sec_keyblock );
1148 }
1149
1150
1151 /****************
1152  * Remove some of the secondary keys
1153  */
1154 static void
1155 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1156 {
1157     KBNODE node;
1158     int selected=0;
1159
1160     for( node = pub_keyblock; node; node = node->next ) {
1161         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1162             selected = node->flag & NODFLG_SELKEY;
1163             if( selected ) {
1164                 delete_kbnode( node );
1165                 if( sec_keyblock ) {
1166                     KBNODE snode;
1167                     int s_selected = 0;
1168                     u32 ki[2];
1169
1170                     keyid_from_pk( node->pkt->pkt.public_key, ki );
1171                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1172                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1173                             u32 ki2[2];
1174
1175                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1176                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1177                             if( s_selected )
1178                                 delete_kbnode( snode );
1179                         }
1180                         else if( s_selected
1181                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1182                             delete_kbnode( snode );
1183                         else
1184                             s_selected = 0;
1185                     }
1186                 }
1187             }
1188         }
1189         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1190             delete_kbnode( node );
1191         else
1192             selected = 0;
1193     }
1194     commit_kbnode( &pub_keyblock );
1195     if( sec_keyblock )
1196         commit_kbnode( &sec_keyblock );
1197 }
1198
1199
1200 /****************
1201  * Select one user id or remove all selection if index is 0.
1202  * Returns: True if the selection changed;
1203  */
1204 static int
1205 menu_select_uid( KBNODE keyblock, int index )
1206 {
1207     KBNODE node;
1208     int i;
1209
1210     /* first check that the index is valid */
1211     if( index ) {
1212         for( i=0, node = keyblock; node; node = node->next ) {
1213             if( node->pkt->pkttype == PKT_USER_ID ) {
1214                 if( ++i == index )
1215                     break;
1216             }
1217         }
1218         if( !node ) {
1219             tty_printf(_("No user id with index %d\n"), index );
1220             return 0;
1221         }
1222     }
1223     else { /* reset all */
1224         for( i=0, node = keyblock; node; node = node->next ) {
1225             if( node->pkt->pkttype == PKT_USER_ID )
1226                 node->flag &= ~NODFLG_SELUID;
1227         }
1228         return 1;
1229     }
1230     /* and toggle the new index */
1231     for( i=0, node = keyblock; node; node = node->next ) {
1232         if( node->pkt->pkttype == PKT_USER_ID ) {
1233             if( ++i == index )
1234                 if( (node->flag & NODFLG_SELUID) )
1235                     node->flag &= ~NODFLG_SELUID;
1236                 else
1237                     node->flag |= NODFLG_SELUID;
1238         }
1239     }
1240
1241     return 1;
1242 }
1243
1244 /****************
1245  * Select secondary keys
1246  * Returns: True if the selection changed;
1247  */
1248 static int
1249 menu_select_key( KBNODE keyblock, int index )
1250 {
1251     KBNODE node;
1252     int i;
1253
1254     /* first check that the index is valid */
1255     if( index ) {
1256         for( i=0, node = keyblock; node; node = node->next ) {
1257             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1258                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1259                 if( ++i == index )
1260                     break;
1261             }
1262         }
1263         if( !node ) {
1264             tty_printf(_("No secondary key with index %d\n"), index );
1265             return 0;
1266         }
1267     }
1268     else { /* reset all */
1269         for( i=0, node = keyblock; node; node = node->next ) {
1270             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1271                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1272                 node->flag &= ~NODFLG_SELKEY;
1273         }
1274         return 1;
1275     }
1276     /* and set the new index */
1277     for( i=0, node = keyblock; node; node = node->next ) {
1278         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1279             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1280             if( ++i == index )
1281                 if( (node->flag & NODFLG_SELKEY) )
1282                     node->flag &= ~NODFLG_SELKEY;
1283                 else
1284                     node->flag |= NODFLG_SELKEY;
1285         }
1286     }
1287
1288     return 1;
1289 }
1290
1291
1292 static int
1293 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1294 {
1295     KBNODE node;
1296     int i=0;
1297
1298     for( node = keyblock; node; node = node->next )
1299         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1300             i++;
1301     return i;
1302 }
1303
1304 static int
1305 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1306 {
1307     KBNODE node;
1308     int i=0;
1309
1310     for( node = keyblock; node; node = node->next )
1311         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1312               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1313             && (node->flag & flag) )
1314             i++;
1315     return i;
1316 }
1317
1318 static int
1319 count_uids( KBNODE keyblock )
1320 {
1321     KBNODE node;
1322     int i=0;
1323
1324     for( node = keyblock; node; node = node->next )
1325         if( node->pkt->pkttype == PKT_USER_ID )
1326             i++;
1327     return i;
1328 }
1329
1330
1331 /****************
1332  * Returns true if there is at least one selected user id
1333  */
1334 static int
1335 count_selected_uids( KBNODE keyblock )
1336 {
1337     return count_uids_with_flag( keyblock, NODFLG_SELUID);
1338 }
1339
1340 static int
1341 count_selected_keys( KBNODE keyblock )
1342 {
1343     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
1344 }
1345