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