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