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