See ChangeLog: Wed Apr 28 13:03:03 CEST 1999 Werner Koch
[gnupg.git] / g10 / keyedit.c
1 /* keyedit.c - keyedit stuff
2  *      Copyright (C) 1998, 1999 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_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
52 static int menu_select_uid( KBNODE keyblock, int idx );
53 static int menu_select_key( KBNODE keyblock, int idx );
54 static int count_uids( KBNODE keyblock );
55 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
56 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
57 static int count_selected_uids( KBNODE keyblock );
58 static int count_selected_keys( KBNODE keyblock );
59 static int menu_revsig( KBNODE keyblock );
60 static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
61
62 #define CONTROL_D ('D' - 'A' + 1)
63
64 #define NODFLG_BADSIG (1<<0)  /* bad signature */
65 #define NODFLG_NOKEY  (1<<1)  /* no public key */
66 #define NODFLG_SIGERR (1<<2)  /* other sig error */
67
68 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
69
70 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
71 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
72 #define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
73
74
75 struct sign_uid_attrib {
76     int non_exportable;
77 };
78
79
80
81
82 static int
83 get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
84 {
85     int rc;
86
87     *keyblock = NULL;
88     /* search the userid */
89     rc = find_keyblock_byname( kbpos, username );
90     if( rc ) {
91         log_error(_("%s: user not found\n"), username );
92         return rc;
93     }
94
95     /* read the keyblock */
96     rc = read_keyblock( kbpos, keyblock );
97     if( rc )
98         log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
99     else
100         merge_keys_and_selfsig( *keyblock );
101
102     return rc;
103 }
104
105
106 /****************
107  * Check the keysigs and set the flags to indicate errors.
108  * Returns true if error found.
109  */
110 static int
111 check_all_keysigs( KBNODE keyblock, int only_selected )
112 {
113     KBNODE kbctx;
114     KBNODE node;
115     int rc;
116     int inv_sigs = 0;
117     int no_key = 0;
118     int oth_err = 0;
119     int has_selfsig = 0;
120     int mis_selfsig = 0;
121     int selected = !only_selected;
122     int anyuid = 0;
123
124     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
125         int is_rev = 0;
126
127         if( node->pkt->pkttype == PKT_USER_ID ) {
128             PKT_user_id *uid = node->pkt->pkt.user_id;
129
130             if( only_selected )
131                 selected = (node->flag & NODFLG_SELUID);
132             if( selected ) {
133                 tty_printf("uid  ");
134                 tty_print_string( uid->name, uid->len );
135                 tty_printf("\n");
136                 if( anyuid && !has_selfsig )
137                     mis_selfsig++;
138                 has_selfsig = 0;
139                 anyuid = 1;
140             }
141         }
142         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
143                  && (node->pkt->pkt.signature->sig_class&~3) == 0x10
144                  && (is_rev = node->pkt->pkt.signature->sig_class == 0x30) ) {
145             PKT_signature *sig = node->pkt->pkt.signature;
146             int sigrc, selfsig;
147
148             switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
149               case 0:
150                 node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
151                 sigrc = '!';
152                 break;
153               case G10ERR_BAD_SIGN:
154                 node->flag = NODFLG_BADSIG;
155                 sigrc = '-';
156                 inv_sigs++;
157                 break;
158               case G10ERR_NO_PUBKEY:
159                 node->flag = NODFLG_NOKEY;
160                 sigrc = '?';
161                 no_key++;
162                 break;
163               default:
164                 node->flag = NODFLG_SIGERR;
165                 sigrc = '%';
166                 oth_err++;
167                 break;
168             }
169             if( sigrc != '?' ) {
170                 tty_printf("%s%c       %08lX %s   ",
171                         is_rev? "rev":"sig",
172                         sigrc, sig->keyid[1], datestr_from_sig(sig));
173                 if( sigrc == '%' )
174                     tty_printf("[%s] ", g10_errstr(rc) );
175                 else if( sigrc == '?' )
176                     ;
177                 else if( selfsig ) {
178                     tty_printf( is_rev? _("[revocation]")
179                                       : _("[self-signature]") );
180                     if( sigrc == '!' )
181                         has_selfsig = 1;
182                 }
183                 else {
184                     size_t n;
185                     char *p = get_user_id( sig->keyid, &n );
186                     tty_print_string( p, n > 40? 40 : n );
187                     m_free(p);
188                 }
189                 tty_printf("\n");
190                 /* fixme: Should we update the trustdb here */
191             }
192         }
193     }
194     if( !has_selfsig )
195         mis_selfsig++;
196     if( inv_sigs == 1 )
197         tty_printf(_("1 bad signature\n"), inv_sigs );
198     else if( inv_sigs )
199         tty_printf(_("%d bad signatures\n"), inv_sigs );
200     if( no_key == 1 )
201         tty_printf(_("1 signature not checked due to a missing key\n") );
202     else if( no_key )
203         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
204     if( oth_err == 1 )
205         tty_printf(_("1 signature not checked due to an error\n") );
206     else if( oth_err )
207         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
208     if( mis_selfsig == 1 )
209         tty_printf(_("1 user id without valid self-signature detected\n"));
210     else if( mis_selfsig  )
211         tty_printf(_("%d user ids without valid self-signatures detected\n"),
212                                                                     mis_selfsig);
213
214     return inv_sigs || no_key || oth_err || mis_selfsig;
215 }
216
217
218
219
220 int
221 sign_uid_mk_attrib( PKT_signature *sig, void *opaque )
222 {
223     struct sign_uid_attrib *attrib = opaque;
224     byte buf[8];
225
226     if( attrib->non_exportable ) {
227         buf[0] = 0; /* not exportable */
228         build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
229     }
230
231     return 0;
232 }
233
234
235
236 /****************
237  * Loop over all locusr and and sign the uids after asking.
238  * If no user id is marked, all user ids will be signed;
239  * if some user_ids are marked those will be signed.
240  */
241 static int
242 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified, int local )
243 {
244     int rc = 0;
245     SK_LIST sk_list = NULL;
246     SK_LIST sk_rover = NULL;
247     PKT_secret_key *sk = NULL;
248     KBNODE node, uidnode;
249     PKT_public_key *primary_pk=NULL;
250     int select_all = !count_selected_uids(keyblock);
251     int upd_trust = 0;
252
253     /* build a list of all signators */
254     rc=build_sk_list( locusr, &sk_list, 0, 1 );
255     if( rc )
256         goto leave;
257
258     /* loop over all signaturs */
259     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
260         u32 sk_keyid[2];
261         size_t n;
262         char *p;
263
264         /* we have to use a copy of the sk, because make_keysig_packet
265          * may remove the protection from sk and if we did other
266          * changes to the secret key, we would save the unprotected
267          * version */
268         if( sk )
269             free_secret_key(sk);
270         sk = copy_secret_key( NULL, sk_rover->sk );
271         keyid_from_sk( sk, sk_keyid );
272         /* set mark A for all selected user ids */
273         for( node=keyblock; node; node = node->next ) {
274             if( select_all || (node->flag & NODFLG_SELUID) )
275                 node->flag |= NODFLG_MARK_A;
276             else
277                 node->flag &= ~NODFLG_MARK_A;
278         }
279         /* reset mark for uids which are already signed */
280         uidnode = NULL;
281         for( node=keyblock; node; node = node->next ) {
282             if( node->pkt->pkttype == PKT_USER_ID ) {
283                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
284             }
285             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
286                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
287                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
288                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
289                     /* Fixme: see whether there is a revocation in which
290                      * case we should allow to sign it again. */
291                     tty_printf(_("Already signed by key %08lX\n"),
292                                                         (ulong)sk_keyid[1] );
293                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
294                 }
295             }
296         }
297         /* check whether any uids are left for signing */
298         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
299             tty_printf(_("Nothing to sign with key %08lX\n"),
300                                                   (ulong)sk_keyid[1] );
301             continue;
302         }
303         /* Ask whether we really should sign these user id(s) */
304         tty_printf("\n");
305         show_key_with_all_names( keyblock, 1, 1, 0, 0 );
306         tty_printf("\n");
307         tty_printf(_(
308              "Are you really sure that you want to sign this key\n"
309              "with your key: \""));
310         p = get_user_id( sk_keyid, &n );
311         tty_print_string( p, n );
312         m_free(p); p = NULL;
313         tty_printf("\"\n\n");
314
315         if( local )
316             tty_printf(
317                   _("The signature will be marked as non-exportable.\n\n"));
318
319
320         if( opt.batch && opt.answer_yes )
321             ;
322         else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
323             continue;
324         /* now we can sign the user ids */
325       reloop: /* (must use this, because we are modifing the list) */
326         primary_pk = NULL;
327         for( node=keyblock; node; node = node->next ) {
328             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
329                 primary_pk = node->pkt->pkt.public_key;
330             else if( node->pkt->pkttype == PKT_USER_ID
331                      && (node->flag & NODFLG_MARK_A) ) {
332                 PACKET *pkt;
333                 PKT_signature *sig;
334                 struct sign_uid_attrib attrib;
335
336                 assert( primary_pk );
337                 memset( &attrib, 0, sizeof attrib );
338                 attrib.non_exportable = local;
339                 node->flag &= ~NODFLG_MARK_A;
340                 rc = make_keysig_packet( &sig, primary_pk,
341                                                node->pkt->pkt.user_id,
342                                                NULL,
343                                                sk,
344                                                0x10, 0,
345                                                sign_uid_mk_attrib,
346                                                &attrib );
347                 if( rc ) {
348                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
349                     goto leave;
350                 }
351                 *ret_modified = 1; /* we changed the keyblock */
352                 upd_trust = 1;
353
354                 pkt = m_alloc_clear( sizeof *pkt );
355                 pkt->pkttype = PKT_SIGNATURE;
356                 pkt->pkt.signature = sig;
357                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
358                 goto reloop;
359             }
360         }
361     } /* end loop over signators */
362     if( upd_trust && primary_pk ) {
363         rc = clear_trust_checked_flag( primary_pk );
364     }
365
366
367   leave:
368     release_sk_list( sk_list );
369     if( sk )
370         free_secret_key(sk);
371     return rc;
372 }
373
374
375
376 /****************
377  * Change the passphrase of the primary and all secondary keys.
378  * We use only one passphrase for all keys.
379  */
380 static int
381 change_passphrase( KBNODE keyblock )
382 {
383     int rc = 0;
384     int changed=0;
385     KBNODE node;
386     PKT_secret_key *sk;
387     char *passphrase = NULL;
388
389     node = find_kbnode( keyblock, PKT_SECRET_KEY );
390     if( !node ) {
391         log_error("Oops; secret key not found anymore!\n");
392         goto leave;
393     }
394     sk = node->pkt->pkt.secret_key;
395
396     switch( is_secret_key_protected( sk ) ) {
397       case -1:
398         rc = G10ERR_PUBKEY_ALGO;
399         break;
400       case 0:
401         tty_printf(_("This key is not protected.\n"));
402         break;
403       default:
404         tty_printf(_("Key is protected.\n"));
405         rc = check_secret_key( sk, 0 );
406         if( !rc )
407             passphrase = get_last_passphrase();
408         break;
409     }
410
411     /* unprotect all subkeys (use the supplied passphrase or ask)*/
412     for(node=keyblock; !rc && node; node = node->next ) {
413         if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
414             PKT_secret_key *subsk = node->pkt->pkt.secret_key;
415             set_next_passphrase( passphrase );
416             rc = check_secret_key( subsk, 0 );
417         }
418     }
419
420     if( rc )
421         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
422     else {
423         DEK *dek = NULL;
424         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
425
426         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
427
428         set_next_passphrase( NULL );
429         for(;;) {
430             s2k->mode = opt.s2k_mode;
431             s2k->hash_algo = opt.s2k_digest_algo;
432             dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
433             if( !dek ) {
434                 tty_printf(_("passphrase not correctly repeated; try again.\n"));
435             }
436             else if( !dek->keylen ) {
437                 rc = 0;
438                 tty_printf(_( "You don't want a passphrase -"
439                             " this is probably a *bad* idea!\n\n"));
440                 if( cpr_get_answer_is_yes("change_passwd.empty.okay",
441                                _("Do you really want to do this? ")))
442                     changed++;
443                 break;
444             }
445             else { /* okay */
446                 sk->protect.algo = dek->algo;
447                 sk->protect.s2k = *s2k;
448                 rc = protect_secret_key( sk, dek );
449                 for(node=keyblock; !rc && node; node = node->next ) {
450                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
451                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
452                         subsk->protect.algo = dek->algo;
453                         subsk->protect.s2k = *s2k;
454                         rc = protect_secret_key( subsk, dek );
455                     }
456                 }
457                 if( rc )
458                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
459                 else
460                     changed++;
461                 break;
462             }
463         }
464         m_free(s2k);
465         m_free(dek);
466     }
467
468   leave:
469     m_free( passphrase );
470     set_next_passphrase( NULL );
471     return changed && !rc;
472 }
473
474
475 /****************
476  * There are some keys out (due to a bug in gnupg), where the sequence
477  * of the packets is wrong.  This function fixes that.
478  * Returns: true if the keyblock has fixed.
479  */
480 static int
481 fix_keyblock( KBNODE keyblock )
482 {
483     KBNODE node, last, subkey;
484     int fixed=0;
485
486     /* locate key signatures of class 0x10..0x13 behind sub key packets */
487     for( subkey=last=NULL, node = keyblock; node;
488                                             last=node, node = node->next ) {
489         switch( node->pkt->pkttype ) {
490           case PKT_PUBLIC_SUBKEY:
491           case PKT_SECRET_SUBKEY:
492             if( !subkey )
493                 subkey = last; /* actually it is the one before the subkey */
494             break;
495           case PKT_SIGNATURE:
496             if( subkey ) {
497                 PKT_signature *sig = node->pkt->pkt.signature;
498                 if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
499                     log_info(_(
500                         "moving a key signature to the correct place\n"));
501                     last->next = node->next;
502                     node->next = subkey->next;
503                     subkey->next = node;
504                     node = last;
505                     fixed=1;
506                 }
507             }
508             break;
509           default: break;
510         }
511     }
512
513     return fixed;
514 }
515
516 /****************
517  * Menu driven key editor
518  *
519  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
520  */
521
522 void
523 keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
524 {
525     enum cmdids { cmdNONE = 0,
526            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
527            cmdLSIGN, cmdREVSIG, cmdREVKEY,
528            cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
529            cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
530            cmdNOP };
531     static struct { const char *name;
532                     enum cmdids id;
533                     int need_sk;
534                     const char *desc;
535                   } cmds[] = {
536         { N_("quit")    , cmdQUIT   , 0, N_("quit this menu") },
537         { N_("q")       , cmdQUIT   , 0, NULL   },
538         { N_("save")    , cmdSAVE   , 0, N_("save and quit") },
539         { N_("help")    , cmdHELP   , 0, N_("show this help") },
540         {    "?"        , cmdHELP   , 0, NULL   },
541         { N_("fpr")     , cmdFPR    , 0, N_("show fingerprint") },
542         { N_("list")    , cmdLIST   , 0, N_("list key and user ids") },
543         { N_("l")       , cmdLIST   , 0, NULL   },
544         { N_("uid")     , cmdSELUID , 0, N_("select user id N") },
545         { N_("key")     , cmdSELKEY , 0, N_("select secondary key N") },
546         { N_("check")   , cmdCHECK  , 0, N_("list signatures") },
547         { N_("c")       , cmdCHECK  , 0, NULL },
548         { N_("sign")    , cmdSIGN   , 0, N_("sign the key") },
549         { N_("s")       , cmdSIGN   , 0, NULL },
550         { N_("lsign")   , cmdLSIGN  , 0, N_("sign the key locally") },
551         { N_("debug")   , cmdDEBUG  , 0, NULL },
552         { N_("adduid")  , cmdADDUID , 1, N_("add a user id") },
553         { N_("deluid")  , cmdDELUID , 0, N_("delete user id") },
554         { N_("addkey")  , cmdADDKEY , 1, N_("add a secondary key") },
555         { N_("delkey")  , cmdDELKEY , 0, N_("delete a secondary key") },
556         { N_("expire")  , cmdEXPIRE , 1, N_("change the expire date") },
557         { N_("toggle")  , cmdTOGGLE , 1, N_("toggle between secret "
558                                             "and public key listing") },
559         { N_("t"     )  , cmdTOGGLE , 1, NULL },
560         { N_("pref")    , cmdPREF  , 0, N_("list preferences") },
561         { N_("passwd")  , cmdPASSWD , 1, N_("change the passphrase") },
562         { N_("trust")   , cmdTRUST , 0, N_("change the ownertrust") },
563         { N_("revsig")  , cmdREVSIG , 0, N_("revoke signatures") },
564         { N_("revkey")  , cmdREVKEY , 1, N_("revoke a secondary key") },
565
566     { NULL, cmdNONE } };
567     enum cmdids cmd;
568     int rc = 0;
569     KBNODE keyblock = NULL;
570     KBPOS keyblockpos;
571     KBNODE sec_keyblock = NULL;
572     KBPOS sec_keyblockpos;
573     KBNODE cur_keyblock;
574     char *answer = NULL;
575     int redisplay = 1;
576     int modified = 0;
577     int sec_modified = 0;
578     int toggle;
579     int have_commands = !!commands;
580
581
582     if( opt.batch && !have_commands ) {
583         log_error(_("can't do that in batchmode\n"));
584         goto leave;
585     }
586
587     /* first try to locate it as secret key */
588     rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
589     if( !rc ) {
590         rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
591         if( rc ) {
592             log_error("%s: secret keyblock read problem: %s\n",
593                                             username, g10_errstr(rc));
594             goto leave;
595         }
596         merge_keys_and_selfsig( sec_keyblock );
597         if( fix_keyblock( sec_keyblock ) )
598             sec_modified++;
599     }
600
601     /* and now get the public key */
602     rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
603     if( rc )
604         goto leave;
605     if( fix_keyblock( keyblock ) )
606         modified++;
607
608     if( sec_keyblock ) { /* check that they match */
609         /* FIXME: check that they both match */
610         tty_printf(_("Secret key is available.\n"));
611     }
612
613     toggle = 0;
614     cur_keyblock = keyblock;
615     for(;;) { /* main loop */
616         int i, arg_number;
617         char *p;
618
619         tty_printf("\n");
620         if( redisplay ) {
621             show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
622             tty_printf("\n");
623             redisplay = 0;
624         }
625         do {
626             m_free(answer);
627             if( have_commands ) {
628                 if( commands ) {
629                     answer = m_strdup( commands->d );
630                     commands = commands->next;
631                 }
632                 else if( opt.batch ) {
633                     answer = m_strdup("quit");
634                 }
635                 else
636                     have_commands = 0;
637             }
638             if( !have_commands ) {
639                 answer = cpr_get("keyedit.cmd", _("Command> "));
640                 cpr_kill_prompt();
641             }
642             trim_spaces(answer);
643         } while( *answer == '#' );
644
645         arg_number = 0;
646         if( !*answer )
647             cmd = cmdLIST;
648         else if( *answer == CONTROL_D )
649             cmd = cmdQUIT;
650         else if( isdigit( *answer ) ) {
651             cmd = cmdSELUID;
652             arg_number = atoi(answer);
653         }
654         else {
655             if( (p=strchr(answer,' ')) ) {
656                 *p++ = 0;
657                 trim_spaces(answer);
658                 trim_spaces(p);
659                 arg_number = atoi(p);
660             }
661
662             for(i=0; cmds[i].name; i++ )
663                 if( !stricmp( answer, cmds[i].name ) )
664                     break;
665             if( cmds[i].need_sk && !sec_keyblock ) {
666                 tty_printf(_("Need the secret key to do this.\n"));
667                 cmd = cmdNOP;
668             }
669             else
670                 cmd = cmds[i].id;
671         }
672         switch( cmd )  {
673           case cmdHELP:
674             for(i=0; cmds[i].name; i++ ) {
675                 if( cmds[i].need_sk && !sec_keyblock )
676                     ; /* skip if we do not have the secret key */
677                 else if( cmds[i].desc )
678                     tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
679             }
680             break;
681
682           case cmdQUIT:
683             if( have_commands )
684                 goto leave;
685             if( !modified && !sec_modified )
686                 goto leave;
687             if( !cpr_get_answer_is_yes("keyedit.save.okay",
688                                         _("Save changes? ")) ) {
689                 if( cpr_enabled()
690                     || cpr_get_answer_is_yes("keyedit.cancel.okay",
691                                              _("Quit without saving? ")) )
692                     goto leave;
693                 break;
694             }
695             /* fall thru */
696           case cmdSAVE:
697             if( modified || sec_modified  ) {
698                 if( modified ) {
699                     rc = update_keyblock( &keyblockpos, keyblock );
700                     if( rc ) {
701                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
702                         break;
703                     }
704                 }
705                 if( sec_modified ) {
706                     rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
707                     if( rc ) {
708                         log_error(_("update secret failed: %s\n"),
709                                                             g10_errstr(rc) );
710                         break;
711                     }
712                 }
713             }
714             else
715                 tty_printf(_("Key not changed so no update needed.\n"));
716             rc = update_trust_record( keyblock, 0, NULL );
717             if( rc )
718                 log_error(_("update of trustdb failed: %s\n"),
719                             g10_errstr(rc) );
720             goto leave;
721
722           case cmdLIST:
723             redisplay = 1;
724             break;
725
726           case cmdFPR:
727             show_key_and_fingerprint( keyblock );
728             break;
729
730           case cmdSELUID:
731             if( menu_select_uid( cur_keyblock, arg_number ) )
732                 redisplay = 1;
733             break;
734
735           case cmdSELKEY:
736             if( menu_select_key( cur_keyblock, arg_number ) )
737                 redisplay = 1;
738             break;
739
740           case cmdCHECK:
741             /* we can only do this with the public key becuase the
742              * check functions can't cope with secret keys and it
743              * is questionable whether this would make sense at all */
744             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
745             break;
746
747           case cmdSIGN: /* sign (only the public key) */
748           case cmdLSIGN: /* sign (only the public key) */
749             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
750                 if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
751                                            _("Really sign all user ids? ")) ) {
752                     tty_printf(_("Hint: Select the user ids to sign\n"));
753                     break;
754                 }
755             }
756             sign_uids( keyblock, locusr, &modified, cmd == cmdLSIGN );
757             break;
758
759           case cmdDEBUG:
760             dump_kbnode( cur_keyblock );
761             break;
762
763           case cmdTOGGLE:
764             toggle = !toggle;
765             cur_keyblock = toggle? sec_keyblock : keyblock;
766             redisplay = 1;
767             break;
768
769           case cmdADDUID:
770             if( menu_adduid( keyblock, sec_keyblock ) ) {
771                 redisplay = 1;
772                 sec_modified = modified = 1;
773                 /* must update the trustdb already here, so that preferences
774                  * get listed correctly */
775                 rc = update_trust_record( keyblock, 0, NULL );
776                 if( rc ) {
777                     log_error(_("update of trustdb failed: %s\n"),
778                                 g10_errstr(rc) );
779                     rc = 0;
780                 }
781             }
782             break;
783
784           case cmdDELUID: {
785                 int n1;
786
787                 if( !(n1=count_selected_uids(keyblock)) )
788                     tty_printf(_("You must select at least one user id.\n"));
789                 else if( count_uids(keyblock) - n1 < 1 )
790                     tty_printf(_("You can't delete the last user id!\n"));
791                 else if( cpr_get_answer_is_yes(
792                             "keyedit.remove.uid.okay",
793                         n1 > 1? _("Really remove all selected user ids? ")
794                               : _("Really remove this user id? ")
795                        ) ) {
796                     menu_deluid( keyblock, sec_keyblock );
797                     redisplay = 1;
798                     modified = 1;
799                     if( sec_keyblock )
800                        sec_modified = 1;
801                 }
802             }
803             break;
804
805           case cmdADDKEY:
806             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
807                 redisplay = 1;
808                 sec_modified = modified = 1;
809             }
810             break;
811
812
813           case cmdDELKEY: {
814                 int n1;
815
816                 if( !(n1=count_selected_keys( keyblock )) )
817                     tty_printf(_("You must select at least one key.\n"));
818                 else if( sec_keyblock && !cpr_get_answer_is_yes(
819                             "keyedit.remove.subkey.okay",
820                        n1 > 1?
821                         _("Do you really want to delete the selected keys? "):
822                         _("Do you really want to delete this key? ")
823                        ))
824                     ;
825                 else {
826                     menu_delkey( keyblock, sec_keyblock );
827                     redisplay = 1;
828                     modified = 1;
829                     if( sec_keyblock )
830                        sec_modified = 1;
831                 }
832             }
833             break;
834
835           case cmdREVKEY: {
836                 int n1;
837
838                 if( !(n1=count_selected_keys( keyblock )) )
839                     tty_printf(_("You must select at least one key.\n"));
840                 else if( sec_keyblock && !cpr_get_answer_is_yes(
841                             "keyedit.revoke.subkey.okay",
842                        n1 > 1?
843                         _("Do you really want to revoke the selected keys? "):
844                         _("Do you really want to revoke this key? ")
845                        ))
846                     ;
847                 else {
848                     if( menu_revkey( keyblock, sec_keyblock ) ) {
849                         modified = 1;
850                         /*sec_modified = 1;*/
851                     }
852                     redisplay = 1;
853                 }
854             }
855             break;
856
857           case cmdEXPIRE:
858             if( menu_expire( keyblock, sec_keyblock ) ) {
859                 merge_keys_and_selfsig( sec_keyblock );
860                 merge_keys_and_selfsig( keyblock );
861                 sec_modified = 1;
862                 modified = 1;
863                 redisplay = 1;
864             }
865             break;
866
867           case cmdPASSWD:
868             if( change_passphrase( sec_keyblock ) )
869                 sec_modified = 1;
870             break;
871
872           case cmdTRUST:
873             show_key_with_all_names( keyblock, 0, 0, 1, 0 );
874             tty_printf("\n");
875             if( edit_ownertrust( find_kbnode( keyblock,
876                       PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
877                 redisplay = 1;
878             /* we don't need to set modified here, as the trustvalues
879              * are updated immediately */
880             break;
881
882           case cmdPREF:
883             show_key_with_all_names( keyblock, 0, 0, 0, 1 );
884             break;
885
886           case cmdNOP:
887             break;
888
889           case cmdREVSIG:
890             if( menu_revsig( keyblock ) ) {
891                 redisplay = 1;
892                 modified = 1;
893             }
894             break;
895
896           default:
897             tty_printf("\n");
898             tty_printf(_("Invalid command  (try \"help\")\n"));
899             break;
900         }
901     } /* end main loop */
902
903   leave:
904     release_kbnode( keyblock );
905     release_kbnode( sec_keyblock );
906     m_free(answer);
907 }
908
909
910 /****************
911  * show preferences of a public keyblock.
912  */
913 static void
914 show_prefs( KBNODE keyblock, PKT_user_id *uid )
915 {
916     KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
917     PKT_public_key *pk;
918     byte *p;
919     int i;
920     size_t n;
921     byte namehash[20];
922
923     if( !node )
924         return; /* is a secret keyblock */
925     pk = node->pkt->pkt.public_key;
926     if( !pk->local_id ) {
927         log_error("oops: no LID\n");
928         return;
929     }
930
931     rmd160_hash_buffer( namehash, uid->name, uid->len );
932
933     p = get_pref_data( pk->local_id, namehash, &n );
934     if( !p )
935         return;
936
937     tty_printf("    ");
938     for(i=0; i < n; i+=2 ) {
939         if( p[i] )
940             tty_printf( " %c%d", p[i] == PREFTYPE_SYM    ? 'S' :
941                                  p[i] == PREFTYPE_HASH   ? 'H' :
942                                  p[i] == PREFTYPE_COMPR  ? 'Z' : '?', p[i+1]);
943     }
944     tty_printf("\n");
945
946     m_free(p);
947 }
948
949
950 /****************
951  * Display the key a the user ids, if only_marked is true, do only
952  * so for user ids with mark A flag set and dont display the index number
953  */
954 static void
955 show_key_with_all_names( KBNODE keyblock, int only_marked,
956                          int with_fpr, int with_subkeys, int with_prefs )
957 {
958     KBNODE node;
959     int i;
960
961     /* the keys */
962     for( node = keyblock; node; node = node->next ) {
963         if( node->pkt->pkttype == PKT_PUBLIC_KEY
964             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
965             PKT_public_key *pk = node->pkt->pkt.public_key;
966             int otrust=0, trust=0;
967
968             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
969                 /* do it here, so that debug messages don't clutter the
970                  * output */
971                 trust = query_trust_info(pk, NULL);
972                 otrust = get_ownertrust_info( pk->local_id );
973             }
974
975             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s",
976                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
977                           (node->flag & NODFLG_SELKEY)? '*':' ',
978                           nbits_from_pk( pk ),
979                           pubkey_letter( pk->pubkey_algo ),
980                           (ulong)keyid_from_pk(pk,NULL),
981                           datestr_from_pk(pk),
982                           expirestr_from_pk(pk) );
983             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
984                 tty_printf(" trust: %c/%c", otrust, trust );
985                 if( with_fpr  ) {
986                     tty_printf("\n");
987                     show_fingerprint( pk );
988                 }
989             }
990             tty_printf("\n");
991         }
992         else if( node->pkt->pkttype == PKT_SECRET_KEY
993             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
994             PKT_secret_key *sk = node->pkt->pkt.secret_key;
995             tty_printf("%s%c %4u%c/%08lX  created: %s expires: %s\n",
996                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
997                           (node->flag & NODFLG_SELKEY)? '*':' ',
998                           nbits_from_sk( sk ),
999                           pubkey_letter( sk->pubkey_algo ),
1000                           (ulong)keyid_from_sk(sk,NULL),
1001                           datestr_from_sk(sk),
1002                           expirestr_from_sk(sk) );
1003         }
1004     }
1005     /* the user ids */
1006     i = 0;
1007     for( node = keyblock; node; node = node->next ) {
1008         if( node->pkt->pkttype == PKT_USER_ID ) {
1009             PKT_user_id *uid = node->pkt->pkt.user_id;
1010             ++i;
1011             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
1012                 if( only_marked )
1013                    tty_printf("     ");
1014                 else if( node->flag & NODFLG_SELUID )
1015                    tty_printf("(%d)* ", i);
1016                 else
1017                    tty_printf("(%d)  ", i);
1018                 tty_print_string( uid->name, uid->len );
1019                 tty_printf("\n");
1020                 if( with_prefs )
1021                     show_prefs( keyblock, uid );
1022             }
1023         }
1024     }
1025 }
1026
1027 static void
1028 show_key_and_fingerprint( KBNODE keyblock )
1029 {
1030     KBNODE node;
1031     PKT_public_key *pk = NULL;
1032
1033     for( node = keyblock; node; node = node->next ) {
1034         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1035             pk = node->pkt->pkt.public_key;
1036             tty_printf("pub  %4u%c/%08lX %s ",
1037                           nbits_from_pk( pk ),
1038                           pubkey_letter( pk->pubkey_algo ),
1039                           (ulong)keyid_from_pk(pk,NULL),
1040                           datestr_from_pk(pk) );
1041         }
1042         else if( node->pkt->pkttype == PKT_USER_ID ) {
1043             PKT_user_id *uid = node->pkt->pkt.user_id;
1044             tty_print_string( uid->name, uid->len );
1045             break;
1046         }
1047     }
1048     tty_printf("\n");
1049     if( pk )
1050         show_fingerprint( pk );
1051 }
1052
1053
1054 static void
1055 show_fingerprint( PKT_public_key *pk )
1056 {
1057     byte array[MAX_FINGERPRINT_LEN], *p;
1058     size_t i, n;
1059
1060     fingerprint_from_pk( pk, array, &n );
1061     p = array;
1062     tty_printf("             Fingerprint:");
1063     if( n == 20 ) {
1064         for(i=0; i < n ; i++, i++, p += 2 ) {
1065             if( i == 10 )
1066                 tty_printf(" ");
1067             tty_printf(" %02X%02X", *p, p[1] );
1068         }
1069     }
1070     else {
1071         for(i=0; i < n ; i++, p++ ) {
1072             if( i && !(i%8) )
1073                 tty_printf(" ");
1074             tty_printf(" %02X", *p );
1075         }
1076     }
1077     tty_printf("\n");
1078 }
1079
1080
1081 /****************
1082  * Ask for a new user id , do the selfsignature and put it into
1083  * both keyblocks.
1084  * Return true if there is a new user id
1085  */
1086 static int
1087 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1088 {
1089     PKT_user_id *uid;
1090     PKT_public_key *pk=NULL;
1091     PKT_secret_key *sk=NULL;
1092     PKT_signature *sig=NULL;
1093     PACKET *pkt;
1094     KBNODE node;
1095     KBNODE pub_where=NULL, sec_where=NULL;
1096     int rc;
1097
1098     uid = generate_user_id();
1099     if( !uid )
1100         return 0;
1101
1102     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1103         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1104             pk = node->pkt->pkt.public_key;
1105         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1106             break;
1107     }
1108     if( !node ) /* no subkey */
1109         pub_where = NULL;
1110     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1111         if( node->pkt->pkttype == PKT_SECRET_KEY )
1112             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1113         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1114             break;
1115     }
1116     if( !node ) /* no subkey */
1117         sec_where = NULL;
1118     assert(pk && sk );
1119
1120     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
1121                              keygen_add_std_prefs, pk );
1122     free_secret_key( sk );
1123     if( rc ) {
1124         log_error("signing failed: %s\n", g10_errstr(rc) );
1125         free_user_id(uid);
1126         return 0;
1127     }
1128
1129     /* insert/append to secret keyblock */
1130     pkt = m_alloc_clear( sizeof *pkt );
1131     pkt->pkttype = PKT_USER_ID;
1132     pkt->pkt.user_id = copy_user_id(NULL, uid);
1133     node = new_kbnode(pkt);
1134     if( sec_where )
1135         insert_kbnode( sec_where, node, 0 );
1136     else
1137         add_kbnode( sec_keyblock, node );
1138     pkt = m_alloc_clear( sizeof *pkt );
1139     pkt->pkttype = PKT_SIGNATURE;
1140     pkt->pkt.signature = copy_signature(NULL, sig);
1141     if( sec_where )
1142         insert_kbnode( node, new_kbnode(pkt), 0 );
1143     else
1144         add_kbnode( sec_keyblock, new_kbnode(pkt) );
1145     /* insert/append to public keyblock */
1146     pkt = m_alloc_clear( sizeof *pkt );
1147     pkt->pkttype = PKT_USER_ID;
1148     pkt->pkt.user_id = uid;
1149     node = new_kbnode(pkt);
1150     if( pub_where )
1151         insert_kbnode( pub_where, node, 0 );
1152     else
1153         add_kbnode( pub_keyblock, node );
1154     pkt = m_alloc_clear( sizeof *pkt );
1155     pkt->pkttype = PKT_SIGNATURE;
1156     pkt->pkt.signature = copy_signature(NULL, sig);
1157     if( pub_where )
1158         insert_kbnode( node, new_kbnode(pkt), 0 );
1159     else
1160         add_kbnode( pub_keyblock, new_kbnode(pkt) );
1161     return 1;
1162 }
1163
1164
1165 /****************
1166  * Remove all selceted userids from the keyrings
1167  */
1168 static void
1169 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1170 {
1171     KBNODE node;
1172     int selected=0;
1173
1174     for( node = pub_keyblock; node; node = node->next ) {
1175         if( node->pkt->pkttype == PKT_USER_ID ) {
1176             selected = node->flag & NODFLG_SELUID;
1177             if( selected ) {
1178                 delete_kbnode( node );
1179                 if( sec_keyblock ) {
1180                     KBNODE snode;
1181                     int s_selected = 0;
1182                     PKT_user_id *uid = node->pkt->pkt.user_id;
1183                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1184                         if( snode->pkt->pkttype == PKT_USER_ID ) {
1185                             PKT_user_id *suid = snode->pkt->pkt.user_id;
1186
1187                             s_selected =
1188                                 (uid->len == suid->len
1189                                  && !memcmp( uid->name, suid->name, uid->len));
1190                             if( s_selected )
1191                                 delete_kbnode( snode );
1192                         }
1193                         else if( s_selected
1194                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1195                             delete_kbnode( snode );
1196                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1197                             s_selected = 0;
1198                     }
1199                 }
1200             }
1201         }
1202         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1203             delete_kbnode( node );
1204         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1205             selected = 0;
1206     }
1207     commit_kbnode( &pub_keyblock );
1208     if( sec_keyblock )
1209         commit_kbnode( &sec_keyblock );
1210 }
1211
1212
1213 /****************
1214  * Remove some of the secondary keys
1215  */
1216 static void
1217 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1218 {
1219     KBNODE node;
1220     int selected=0;
1221
1222     for( node = pub_keyblock; node; node = node->next ) {
1223         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1224             selected = node->flag & NODFLG_SELKEY;
1225             if( selected ) {
1226                 delete_kbnode( node );
1227                 if( sec_keyblock ) {
1228                     KBNODE snode;
1229                     int s_selected = 0;
1230                     u32 ki[2];
1231
1232                     keyid_from_pk( node->pkt->pkt.public_key, ki );
1233                     for( snode = sec_keyblock; snode; snode = snode->next ) {
1234                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1235                             u32 ki2[2];
1236
1237                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1238                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1239                             if( s_selected )
1240                                 delete_kbnode( snode );
1241                         }
1242                         else if( s_selected
1243                                  && snode->pkt->pkttype == PKT_SIGNATURE )
1244                             delete_kbnode( snode );
1245                         else
1246                             s_selected = 0;
1247                     }
1248                 }
1249             }
1250         }
1251         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1252             delete_kbnode( node );
1253         else
1254             selected = 0;
1255     }
1256     commit_kbnode( &pub_keyblock );
1257     if( sec_keyblock )
1258         commit_kbnode( &sec_keyblock );
1259 }
1260
1261
1262
1263 static int
1264 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
1265 {
1266     int n1, signumber, rc;
1267     u32 expiredate;
1268     int mainkey=0;
1269     PKT_secret_key *sk;    /* copy of the main sk */
1270     PKT_public_key *main_pk, *sub_pk;
1271     PKT_user_id *uid;
1272     KBNODE node;
1273     u32 keyid[2];
1274
1275     if( count_selected_keys( sec_keyblock ) ) {
1276         tty_printf(_("Please remove selections from the secret keys.\n"));
1277         return 0;
1278     }
1279
1280     n1 = count_selected_keys( pub_keyblock );
1281     if( n1 > 1 ) {
1282         tty_printf(_("Please select at most one secondary key.\n"));
1283         return 0;
1284     }
1285     else if( n1 )
1286         tty_printf(_("Changing exiration time for a secondary key.\n"));
1287     else {
1288         tty_printf(_("Changing exiration time for the primary key.\n"));
1289         mainkey=1;
1290     }
1291
1292     expiredate = ask_expiredate();
1293     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
1294     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1295
1296     /* Now we can actually change the self signature(s) */
1297     main_pk = sub_pk = NULL;
1298     uid = NULL;
1299     signumber = 0;
1300     for( node=pub_keyblock; node; node = node->next ) {
1301         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1302             main_pk = node->pkt->pkt.public_key;
1303             keyid_from_pk( main_pk, keyid );
1304             main_pk->expiredate = expiredate;
1305         }
1306         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1307                  && (node->flag & NODFLG_SELKEY ) ) {
1308             sub_pk = node->pkt->pkt.public_key;
1309             sub_pk->expiredate = expiredate;
1310         }
1311         else if( node->pkt->pkttype == PKT_USER_ID )
1312             uid = node->pkt->pkt.user_id;
1313         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
1314             PKT_signature *sig = node->pkt->pkt.signature;
1315             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
1316                 && (    (mainkey && uid && (sig->sig_class&~3) == 0x10)
1317                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
1318                 /* this is a selfsignature which is to be replaced */
1319                 PKT_signature *newsig;
1320                 PACKET *newpkt;
1321                 KBNODE sn;
1322                 int signumber2 = 0;
1323
1324                 signumber++;
1325
1326                 if( (mainkey && main_pk->version < 4)
1327                     || (!mainkey && sub_pk->version < 4 ) ) {
1328                     log_info(_(
1329                         "You can't change the expiration date of a v3 key\n"));
1330                     free_secret_key( sk );
1331                     return 0;
1332                 }
1333
1334                 /* find the corresponding secret self-signature */
1335                 for( sn=sec_keyblock; sn; sn = sn->next ) {
1336                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
1337                         PKT_signature *b = sn->pkt->pkt.signature;
1338                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
1339                             && sig->sig_class == b->sig_class
1340                             && ++signumber2 == signumber )
1341                             break;
1342                     }
1343                 }
1344                 if( !sn )
1345                     log_info(_("No corresponding signature in secret ring\n"));
1346
1347                 /* create new self signature */
1348                 if( mainkey )
1349                     rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
1350                                              sk, 0x13, 0,
1351                                              keygen_add_std_prefs, main_pk );
1352                 else
1353                     rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
1354                                              sk, 0x18, 0,
1355                                              keygen_add_key_expire, sub_pk );
1356                 if( rc ) {
1357                     log_error("make_keysig_packet failed: %s\n",
1358                                                     g10_errstr(rc));
1359                     free_secret_key( sk );
1360                     return 0;
1361                 }
1362                 /* replace the packet */
1363                 newpkt = m_alloc_clear( sizeof *newpkt );
1364                 newpkt->pkttype = PKT_SIGNATURE;
1365                 newpkt->pkt.signature = newsig;
1366                 free_packet( node->pkt );
1367                 m_free( node->pkt );
1368                 node->pkt = newpkt;
1369                 if( sn ) {
1370                     newpkt = m_alloc_clear( sizeof *newpkt );
1371                     newpkt->pkttype = PKT_SIGNATURE;
1372                     newpkt->pkt.signature = copy_signature( NULL, newsig );
1373                     free_packet( sn->pkt );
1374                     m_free( sn->pkt );
1375                     sn->pkt = newpkt;
1376                 }
1377             }
1378         }
1379     }
1380
1381     free_secret_key( sk );
1382     return 1;
1383 }
1384
1385
1386 /****************
1387  * Select one user id or remove all selection if index is 0.
1388  * Returns: True if the selection changed;
1389  */
1390 static int
1391 menu_select_uid( KBNODE keyblock, int idx )
1392 {
1393     KBNODE node;
1394     int i;
1395
1396     /* first check that the index is valid */
1397     if( idx ) {
1398         for( i=0, node = keyblock; node; node = node->next ) {
1399             if( node->pkt->pkttype == PKT_USER_ID ) {
1400                 if( ++i == idx )
1401                     break;
1402             }
1403         }
1404         if( !node ) {
1405             tty_printf(_("No user id with index %d\n"), idx );
1406             return 0;
1407         }
1408     }
1409     else { /* reset all */
1410         for( i=0, node = keyblock; node; node = node->next ) {
1411             if( node->pkt->pkttype == PKT_USER_ID )
1412                 node->flag &= ~NODFLG_SELUID;
1413         }
1414         return 1;
1415     }
1416     /* and toggle the new index */
1417     for( i=0, node = keyblock; node; node = node->next ) {
1418         if( node->pkt->pkttype == PKT_USER_ID ) {
1419             if( ++i == idx ) {
1420                 if( (node->flag & NODFLG_SELUID) )
1421                     node->flag &= ~NODFLG_SELUID;
1422                 else
1423                     node->flag |= NODFLG_SELUID;
1424             }
1425         }
1426     }
1427
1428     return 1;
1429 }
1430
1431 /****************
1432  * Select secondary keys
1433  * Returns: True if the selection changed;
1434  */
1435 static int
1436 menu_select_key( KBNODE keyblock, int idx )
1437 {
1438     KBNODE node;
1439     int i;
1440
1441     /* first check that the index is valid */
1442     if( idx ) {
1443         for( i=0, node = keyblock; node; node = node->next ) {
1444             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1445                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1446                 if( ++i == idx )
1447                     break;
1448             }
1449         }
1450         if( !node ) {
1451             tty_printf(_("No secondary key with index %d\n"), idx );
1452             return 0;
1453         }
1454     }
1455     else { /* reset all */
1456         for( i=0, node = keyblock; node; node = node->next ) {
1457             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1458                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1459                 node->flag &= ~NODFLG_SELKEY;
1460         }
1461         return 1;
1462     }
1463     /* and set the new index */
1464     for( i=0, node = keyblock; node; node = node->next ) {
1465         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1466             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1467             if( ++i == idx ) {
1468                 if( (node->flag & NODFLG_SELKEY) )
1469                     node->flag &= ~NODFLG_SELKEY;
1470                 else
1471                     node->flag |= NODFLG_SELKEY;
1472             }
1473         }
1474     }
1475
1476     return 1;
1477 }
1478
1479
1480 static int
1481 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1482 {
1483     KBNODE node;
1484     int i=0;
1485
1486     for( node = keyblock; node; node = node->next )
1487         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1488             i++;
1489     return i;
1490 }
1491
1492 static int
1493 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1494 {
1495     KBNODE node;
1496     int i=0;
1497
1498     for( node = keyblock; node; node = node->next )
1499         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1500               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1501             && (node->flag & flag) )
1502             i++;
1503     return i;
1504 }
1505
1506 static int
1507 count_uids( KBNODE keyblock )
1508 {
1509     KBNODE node;
1510     int i=0;
1511
1512     for( node = keyblock; node; node = node->next )
1513         if( node->pkt->pkttype == PKT_USER_ID )
1514             i++;
1515     return i;
1516 }
1517
1518
1519 /****************
1520  * Returns true if there is at least one selected user id
1521  */
1522 static int
1523 count_selected_uids( KBNODE keyblock )
1524 {
1525     return count_uids_with_flag( keyblock, NODFLG_SELUID);
1526 }
1527
1528 static int
1529 count_selected_keys( KBNODE keyblock )
1530 {
1531     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
1532 }
1533
1534 /*
1535  * Ask whether the signature should be revoked.  If the user commits this,
1536  * flag bit MARK_A is set on the signature and the user ID.
1537  */
1538 static void
1539 ask_revoke_sig( KBNODE keyblock, KBNODE node )
1540 {
1541     PKT_signature *sig = node->pkt->pkt.signature;
1542     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
1543
1544     if( !unode ) {
1545         log_error("Oops: no user ID for signature\n");
1546         return;
1547     }
1548
1549     tty_printf(_("user ID: \""));
1550     tty_print_string( unode->pkt->pkt.user_id->name,
1551                       unode->pkt->pkt.user_id->len );
1552     tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
1553                 sig->keyid[1], datestr_from_sig(sig) );
1554
1555     if( cpr_get_answer_is_yes("ask_revoke_sig.one",
1556          _("Create a revocation certificate for this signature? (y/N)")) ) {
1557         node->flag |= NODFLG_MARK_A;
1558         unode->flag |= NODFLG_MARK_A;
1559     }
1560 }
1561
1562 /****************
1563  * Display all user ids of the current public key together with signatures
1564  * done by one of our keys.  Then walk over all this sigs and ask the user
1565  * whether he wants to revoke this signature.
1566  * Return: True when the keyblock has changed.
1567  */
1568 static int
1569 menu_revsig( KBNODE keyblock )
1570 {
1571     PKT_signature *sig;
1572     PKT_public_key *primary_pk;
1573     KBNODE node;
1574     int changed = 0;
1575     int upd_trust = 0;
1576     int rc, any;
1577
1578     /* FIXME: detect duplicates here  */
1579     tty_printf("You have signed these user IDs:\n");
1580     for( node = keyblock; node; node = node->next ) {
1581         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
1582         if( node->pkt->pkttype == PKT_USER_ID ) {
1583             PKT_user_id *uid = node->pkt->pkt.user_id;
1584             /* Hmmm: Should we show only UIDs with a signature? */
1585             tty_printf("     ");
1586             tty_print_string( uid->name, uid->len );
1587             tty_printf("\n");
1588         }
1589         else if( node->pkt->pkttype == PKT_SIGNATURE
1590                 && ((sig = node->pkt->pkt.signature),
1591                      !seckey_available( sig->keyid )  ) ) {
1592             if( (sig->sig_class&~3) == 0x10 ) {
1593                 tty_printf("   signed by %08lX at %s\n",
1594                             sig->keyid[1], datestr_from_sig(sig) );
1595                 node->flag |= NODFLG_SELSIG;
1596             }
1597             else if( sig->sig_class == 0x30 ) {
1598                 tty_printf("   revoked by %08lX at %s\n",
1599                             sig->keyid[1], datestr_from_sig(sig) );
1600             }
1601         }
1602     }
1603
1604     /* ask */
1605     for( node = keyblock; node; node = node->next ) {
1606         if( !(node->flag & NODFLG_SELSIG) )
1607             continue;
1608         ask_revoke_sig( keyblock, node );
1609     }
1610
1611     /* present selected */
1612     any = 0;
1613     for( node = keyblock; node; node = node->next ) {
1614         if( !(node->flag & NODFLG_MARK_A) )
1615             continue;
1616         if( !any ) {
1617             any = 1;
1618             tty_printf("You are about to revoke these signatures:\n");
1619         }
1620         if( node->pkt->pkttype == PKT_USER_ID ) {
1621             PKT_user_id *uid = node->pkt->pkt.user_id;
1622             tty_printf("     ");
1623             tty_print_string( uid->name, uid->len );
1624             tty_printf("\n");
1625         }
1626         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
1627             sig = node->pkt->pkt.signature;
1628             tty_printf("   signed by %08lX at %s\n",
1629                             sig->keyid[1], datestr_from_sig(sig) );
1630         }
1631     }
1632     if( !any )
1633         return 0; /* none selected */
1634
1635     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
1636          _("Really create the revocation certificates? (y/N)")) )
1637         return 0; /* forget it */
1638
1639
1640     /* now we can sign the user ids */
1641   reloop: /* (must use this, because we are modifing the list) */
1642     primary_pk = keyblock->pkt->pkt.public_key;
1643     for( node=keyblock; node; node = node->next ) {
1644         KBNODE unode;
1645         PACKET *pkt;
1646         struct sign_uid_attrib attrib;
1647         PKT_secret_key *sk;
1648
1649         if( !(node->flag & NODFLG_MARK_A)
1650             || node->pkt->pkttype != PKT_SIGNATURE )
1651             continue;
1652         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
1653         assert( unode ); /* we already checked this */
1654
1655         memset( &attrib, 0, sizeof attrib );
1656         node->flag &= ~NODFLG_MARK_A;
1657         sk = m_alloc_secure_clear( sizeof *sk );
1658         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
1659             log_info(_("no secret key\n"));
1660             continue;
1661         }
1662         rc = make_keysig_packet( &sig, primary_pk,
1663                                        unode->pkt->pkt.user_id,
1664                                        NULL,
1665                                        sk,
1666                                        0x30, 0,
1667                                        sign_uid_mk_attrib,
1668                                        &attrib );
1669         free_secret_key(sk);
1670         if( rc ) {
1671             log_error(_("signing failed: %s\n"), g10_errstr(rc));
1672             return changed;
1673         }
1674         changed = 1; /* we changed the keyblock */
1675         upd_trust = 1;
1676
1677         pkt = m_alloc_clear( sizeof *pkt );
1678         pkt->pkttype = PKT_SIGNATURE;
1679         pkt->pkt.signature = sig;
1680         insert_kbnode( unode, new_kbnode(pkt), PKT_SIGNATURE );
1681         goto reloop;
1682     }
1683
1684     if( upd_trust )
1685         clear_trust_checked_flag( primary_pk );
1686
1687     return changed;
1688 }
1689
1690 /****************
1691  * Revoke some of the secondary keys.
1692  * Hmmm: Should we add a revocation to the secret keyring too?
1693  *       Does its all make sense to duplicate most of the information?
1694  */
1695 static int
1696 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1697 {
1698     PKT_public_key *mainpk;
1699     KBNODE node;
1700     int changed = 0;
1701     int upd_trust = 0;
1702     int rc;
1703
1704   reloop: /* (better this way becuase we are modifing the keyring) */
1705     mainpk = pub_keyblock->pkt->pkt.public_key;
1706     for( node = pub_keyblock; node; node = node->next ) {
1707         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1708             && (node->flag & NODFLG_SELKEY) ) {
1709             PACKET *pkt;
1710             PKT_signature *sig;
1711             PKT_secret_key *sk;
1712             PKT_public_key *subpk = node->pkt->pkt.public_key;
1713
1714             node->flag &= ~NODFLG_SELKEY;
1715             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
1716             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk, 0x28, 0,
1717                                      NULL, NULL );
1718             free_secret_key(sk);
1719             if( rc ) {
1720                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
1721                 return changed;
1722             }
1723             changed = 1; /* we changed the keyblock */
1724             upd_trust = 1;
1725
1726             pkt = m_alloc_clear( sizeof *pkt );
1727             pkt->pkttype = PKT_SIGNATURE;
1728             pkt->pkt.signature = sig;
1729             insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
1730             goto reloop;
1731         }
1732     }
1733     commit_kbnode( &pub_keyblock );
1734     /*commit_kbnode( &sec_keyblock );*/
1735
1736     if( upd_trust )
1737         clear_trust_checked_flag( mainpk );
1738
1739     return changed;
1740 }
1741
1742