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