1 /* keyedit.c - keyedit stuff
2 * Copyright (C) 1998 Free Software Foundation, Inc.
4 * This file is part of GNUPG.
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.
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.
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
43 static void show_prefs( KBNODE keyblock, PKT_user_id *uid );
44 static void show_key_with_all_names( KBNODE keyblock,
45 int only_marked, int with_fpr, int with_subkeys, int with_prefs );
46 static void show_key_and_fingerprint( KBNODE keyblock );
47 static void show_fingerprint( PKT_public_key *pk );
48 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
49 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
50 static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
51 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
52 static int menu_select_uid( KBNODE keyblock, int index );
53 static int menu_select_key( KBNODE keyblock, int index );
54 static int count_uids( KBNODE keyblock );
55 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
56 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
57 static int count_selected_uids( KBNODE keyblock );
58 static int count_selected_keys( KBNODE keyblock );
60 #define CONTROL_D ('D' - 'A' + 1)
62 #define NODFLG_BADSIG (1<<0) /* bad signature */
63 #define NODFLG_NOKEY (1<<1) /* no public key */
64 #define NODFLG_SIGERR (1<<2) /* other sig error */
66 #define NODFLG_MARK_A (1<<4) /* temporary mark */
68 #define NODFLG_SELUID (1<<8) /* indicate the selected userid */
69 #define NODFLG_SELKEY (1<<9) /* indicate the selected key */
73 get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
78 /* search the userid */
79 rc = find_keyblock_byname( kbpos, username );
81 log_error(_("%s: user not found\n"), username );
85 /* read the keyblock */
86 rc = read_keyblock( kbpos, keyblock );
88 log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
90 merge_keys_and_selfsig( *keyblock );
97 * Check the keysigs and set the flags to indicate errors.
98 * Returns true if error found.
101 check_all_keysigs( KBNODE keyblock, int only_selected )
111 int selected = !only_selected;
114 for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
115 if( node->pkt->pkttype == PKT_USER_ID ) {
116 PKT_user_id *uid = node->pkt->pkt.user_id;
119 selected = (node->flag & NODFLG_SELUID);
122 tty_print_string( uid->name, uid->len );
124 if( anyuid && !has_selfsig )
130 else if( selected && node->pkt->pkttype == PKT_SIGNATURE
131 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
132 PKT_signature *sig = node->pkt->pkt.signature;
135 switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
137 node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
140 case G10ERR_BAD_SIGN:
141 node->flag = NODFLG_BADSIG;
145 case G10ERR_NO_PUBKEY:
146 node->flag = NODFLG_NOKEY;
151 node->flag = NODFLG_SIGERR;
157 tty_printf("sig%c %08lX %s ",
158 sigrc, sig->keyid[1], datestr_from_sig(sig));
160 tty_printf("[%s] ", g10_errstr(rc) );
161 else if( sigrc == '?' )
164 tty_printf( _("[self-signature]") );
170 char *p = get_user_id( sig->keyid, &n );
171 tty_print_string( p, n > 40? 40 : n );
175 /* fixme: Should we update the trustdb here */
182 tty_printf(_("1 bad signature\n"), inv_sigs );
184 tty_printf(_("%d bad signatures\n"), inv_sigs );
186 tty_printf(_("1 signature not checked due to a missing key\n") );
188 tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
190 tty_printf(_("1 signature not checked due to an error\n") );
192 tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
193 if( mis_selfsig == 1 )
194 tty_printf(_("1 user id without valid self-signature detected\n"));
195 else if( mis_selfsig )
196 tty_printf(_("%d user ids without valid self-signatures detected\n"),
199 return inv_sigs || no_key || oth_err || mis_selfsig;
204 * Loop over all locusr and and sign the uids after asking.
205 * If no user id is marked, all user ids will be signed;
206 * if some user_ids are marked those will be signed.
208 * fixme: Add support for our proposed sign-all scheme
211 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
214 SK_LIST sk_list = NULL;
215 SK_LIST sk_rover = NULL;
216 PKT_secret_key *sk = NULL;
217 KBNODE node, uidnode;
218 PKT_public_key *primary_pk=NULL;
219 int select_all = !count_selected_uids(keyblock);
222 /* build a list of all signators */
223 rc=build_sk_list( locusr, &sk_list, 0, 1 );
227 /* loop over all signaturs */
228 for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
233 /* we have to use a copy of the sk, because make_keysig_packet
234 * may remove the protection from sk and if we did other
235 * changes to the secret key, we would save the unprotected
239 sk = copy_secret_key( NULL, sk_rover->sk );
240 keyid_from_sk( sk, sk_keyid );
241 /* set mark A for all selected user ids */
242 for( node=keyblock; node; node = node->next ) {
243 if( select_all || (node->flag & NODFLG_SELUID) )
244 node->flag |= NODFLG_MARK_A;
246 node->flag &= ~NODFLG_MARK_A;
248 /* reset mark for uids which are already signed */
250 for( node=keyblock; node; node = node->next ) {
251 if( node->pkt->pkttype == PKT_USER_ID ) {
252 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
254 else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
255 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
256 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
257 && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
258 tty_printf(_("Already signed by key %08lX\n"),
259 (ulong)sk_keyid[1] );
260 uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
264 /* check whether any uids are left for signing */
265 if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
266 tty_printf(_("Nothing to sign with key %08lX\n"),
267 (ulong)sk_keyid[1] );
270 /* Ask whether we really should sign these user id(s) */
272 show_key_with_all_names( keyblock, 1, 1, 0, 0 );
275 "Are you really sure that you want to sign this key\n"
276 "with your key: \""));
277 p = get_user_id( sk_keyid, &n );
278 tty_print_string( p, n );
280 tty_printf("\"\n\n");
282 if( !cpr_get_answer_is_yes(N_("sign_uid.okay"), _("Really sign? ")) )
284 /* now we can sign the user ids */
285 reloop: /* (must use this, because we are modifing the list) */
287 for( node=keyblock; node; node = node->next ) {
288 if( node->pkt->pkttype == PKT_PUBLIC_KEY )
289 primary_pk = node->pkt->pkt.public_key;
290 else if( node->pkt->pkttype == PKT_USER_ID
291 && (node->flag & NODFLG_MARK_A) ) {
295 assert( primary_pk );
296 node->flag &= ~NODFLG_MARK_A;
297 rc = make_keysig_packet( &sig, primary_pk,
298 node->pkt->pkt.user_id,
301 0x10, 0, NULL, NULL );
303 log_error(_("signing failed: %s\n"), g10_errstr(rc));
306 *ret_modified = 1; /* we changed the keyblock */
309 pkt = m_alloc_clear( sizeof *pkt );
310 pkt->pkttype = PKT_SIGNATURE;
311 pkt->pkt.signature = sig;
312 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
316 } /* end loop over signators */
317 if( upd_trust && primary_pk ) {
318 rc = clear_trust_checked_flag( primary_pk );
323 release_sk_list( sk_list );
332 * Change the passphrase of the primary and all secondary keys.
333 * We use only one passphrase for all keys.
336 change_passphrase( KBNODE keyblock )
342 char *passphrase = NULL;
344 node = find_kbnode( keyblock, PKT_SECRET_KEY );
346 log_error("Oops; secret key not found anymore!\n");
349 sk = node->pkt->pkt.secret_key;
351 switch( is_secret_key_protected( sk ) ) {
353 rc = G10ERR_PUBKEY_ALGO;
356 tty_printf(_("This key is not protected.\n"));
359 tty_printf(_("Key is protected.\n"));
360 rc = check_secret_key( sk, 0 );
362 passphrase = get_last_passphrase();
366 /* unprotect all subkeys (use the supplied passphrase or ask)*/
367 for(node=keyblock; !rc && node; node = node->next ) {
368 if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
369 PKT_secret_key *subsk = node->pkt->pkt.secret_key;
370 set_next_passphrase( passphrase );
371 rc = check_secret_key( subsk, 0 );
376 tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
379 STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
381 tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
383 set_next_passphrase( NULL );
385 s2k->mode = opt.s2k_mode;
386 s2k->hash_algo = opt.s2k_digest_algo;
387 dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
389 tty_printf(_("passphrase not correctly repeated; try again.\n"));
391 else if( !dek->keylen ) {
393 tty_printf(_( "You don't want a passphrase -"
394 " this is probably a *bad* idea!\n\n"));
395 if( cpr_get_answer_is_yes(N_("change_passwd.empty.okay"),
396 _("Do you really want to do this? ")))
401 sk->protect.algo = dek->algo;
402 sk->protect.s2k = *s2k;
403 rc = protect_secret_key( sk, dek );
404 for(node=keyblock; !rc && node; node = node->next ) {
405 if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
406 PKT_secret_key *subsk = node->pkt->pkt.secret_key;
407 subsk->protect.algo = dek->algo;
408 subsk->protect.s2k = *s2k;
409 rc = protect_secret_key( subsk, dek );
413 log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
424 m_free( passphrase );
425 set_next_passphrase( NULL );
426 return changed && !rc;
431 * There are some keys out (due to a bug in gnupg), where the sequence
432 * of the packets is wrong. This function fixes that.
433 * Returns: true if the keyblock has fixed.
436 fix_keyblock( KBNODE keyblock )
438 KBNODE node, last, subkey;
441 /* locate key signatures of class 0x10..0x13 behind sub key packets */
442 for( subkey=last=NULL, node = keyblock; node;
443 last=node, node = node->next ) {
444 switch( node->pkt->pkttype ) {
445 case PKT_PUBLIC_SUBKEY:
446 case PKT_SECRET_SUBKEY:
448 subkey = last; /* actually it is the one before the subkey */
452 PKT_signature *sig = node->pkt->pkt.signature;
453 if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
455 "moving a key signature to the correct place\n"));
456 last->next = node->next;
457 node->next = subkey->next;
472 * Menu driven key editor
474 * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
478 keyedit_menu( const char *username, STRLIST locusr )
480 enum cmdids { cmdNONE = 0,
481 cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
482 cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
483 cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
485 static struct { const char *name;
490 { N_("quit") , cmdQUIT , 0, N_("quit this menu") },
491 { N_("q") , cmdQUIT , 0, NULL },
492 { N_("save") , cmdSAVE , 0, N_("save and quit") },
493 { N_("help") , cmdHELP , 0, N_("show this help") },
494 { "?" , cmdHELP , 0, NULL },
495 { N_("fpr") , cmdFPR , 0, N_("show fingerprint") },
496 { N_("list") , cmdLIST , 0, N_("list key and user ids") },
497 { N_("l") , cmdLIST , 0, NULL },
498 { N_("uid") , cmdSELUID , 0, N_("select user id N") },
499 { N_("key") , cmdSELKEY , 0, N_("select secondary key N") },
500 { N_("check") , cmdCHECK , 0, N_("list signatures") },
501 { N_("c") , cmdCHECK , 0, NULL },
502 { N_("sign") , cmdSIGN , 0, N_("sign the key") },
503 { N_("s") , cmdSIGN , 0, NULL },
504 { N_("debug") , cmdDEBUG , 0, NULL },
505 { N_("adduid") , cmdADDUID , 1, N_("add a user id") },
506 { N_("deluid") , cmdDELUID , 0, N_("delete user id") },
507 { N_("addkey") , cmdADDKEY , 1, N_("add a secondary key") },
508 { N_("delkey") , cmdDELKEY , 0, N_("delete a secondary key") },
509 { N_("expire") , cmdEXPIRE , 1, N_("change the expire date") },
510 { N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret "
511 "and public key listing") },
512 { N_("t" ) , cmdTOGGLE , 1, NULL },
513 { N_("pref") , cmdPREF , 0, N_("list preferences") },
514 { N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") },
515 { N_("trust") , cmdTRUST , 0, N_("change the ownertrust") },
520 KBNODE keyblock = NULL;
522 KBNODE sec_keyblock = NULL;
523 KBPOS sec_keyblockpos;
528 int sec_modified = 0;
533 log_error(_("can't do that in batchmode\n"));
537 /* first try to locate it as secret key */
538 rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
540 rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
542 log_error("%s: secret keyblock read problem: %s\n",
543 username, g10_errstr(rc));
546 merge_keys_and_selfsig( sec_keyblock );
547 if( fix_keyblock( sec_keyblock ) )
551 /* and now get the public key */
552 rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
555 if( fix_keyblock( keyblock ) )
558 if( sec_keyblock ) { /* check that they match */
559 /* FIXME: check that they both match */
560 tty_printf(_("Secret key is available.\n"));
564 cur_keyblock = keyblock;
565 for(;;) { /* main loop */
571 show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
577 answer = cpr_get(N_("keyedit.cmd"), _("Command> "));
580 } while( *answer == '#' );
585 else if( *answer == CONTROL_D )
587 else if( isdigit( *answer ) ) {
589 arg_number = atoi(answer);
592 if( (p=strchr(answer,' ')) ) {
596 arg_number = atoi(p);
599 for(i=0; cmds[i].name; i++ )
600 if( !stricmp( answer, cmds[i].name ) )
602 if( cmds[i].need_sk && !sec_keyblock ) {
603 tty_printf(_("Need the secret key to to this.\n"));
611 for(i=0; cmds[i].name; i++ ) {
612 if( cmds[i].need_sk && !sec_keyblock )
613 ; /* skip if we do not have the secret key */
614 else if( cmds[i].desc )
615 tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
620 if( !modified && !sec_modified )
622 if( !cpr_get_answer_is_yes(N_("keyedit.save.okay"),
623 _("Save changes? ")) ) {
625 || cpr_get_answer_is_yes(N_("keyedit.cancel.okay"),
626 _("Quit without saving? ")) )
632 if( modified || sec_modified ) {
634 rc = update_keyblock( &keyblockpos, keyblock );
636 log_error(_("update failed: %s\n"), g10_errstr(rc) );
641 rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
643 log_error(_("update secret failed: %s\n"),
650 tty_printf(_("Key not changed so no update needed.\n"));
651 rc = update_trust_record( keyblock, 0, NULL );
653 log_error(_("update of trust db failed: %s\n"),
662 show_key_and_fingerprint( keyblock );
666 if( menu_select_uid( cur_keyblock, arg_number ) )
671 if( menu_select_key( cur_keyblock, arg_number ) )
676 /* we can only do this with the public key becuase the
677 * check functions can't cope with secret keys and it
678 * is questionable whether this would make sense at all */
679 check_all_keysigs( keyblock, count_selected_uids(keyblock) );
682 case cmdSIGN: /* sign (only the public key) */
683 if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
684 if( !cpr_get_answer_is_yes(N_("keyedit.sign_all.okay"),
685 _("Really sign all user ids? ")) ) {
686 tty_printf(_("Hint: Select the user ids to sign\n"));
690 sign_uids( keyblock, locusr, &modified );
694 dump_kbnode( cur_keyblock );
699 cur_keyblock = toggle? sec_keyblock : keyblock;
704 if( menu_adduid( keyblock, sec_keyblock ) ) {
706 sec_modified = modified = 1;
707 /* must update the trustdb already here, so that preferences
708 * get listed correctly */
709 rc = update_trust_record( keyblock, 0, NULL );
711 log_error(_("update of trust db failed: %s\n"),
721 if( !(n1=count_selected_uids(keyblock)) )
722 tty_printf(_("You must select at least one user id.\n"));
723 else if( count_uids(keyblock) - n1 < 1 )
724 tty_printf(_("You can't delete the last user id!\n"));
725 else if( cpr_get_answer_is_yes(
726 N_("keyedit.remove.uid.okay"),
727 n1 > 1? _("Really remove all selected user ids? ")
728 : _("Really remove this user id? ")
730 menu_deluid( keyblock, sec_keyblock );
740 if( generate_subkeypair( keyblock, sec_keyblock ) ) {
742 sec_modified = modified = 1;
750 if( !(n1=count_selected_keys( keyblock )) )
751 tty_printf(_("You must select at least one key.\n"));
752 else if( sec_keyblock && !cpr_get_answer_is_yes(
753 N_("keyedit.remove.subkey.okay"),
755 _("Do you really want to delete the selected keys? "):
756 _("Do you really want to delete this key? ")
760 menu_delkey( keyblock, sec_keyblock );
770 if( menu_expire( keyblock, sec_keyblock ) ) {
771 merge_keys_and_selfsig( sec_keyblock );
772 merge_keys_and_selfsig( keyblock );
780 if( change_passphrase( sec_keyblock ) )
785 show_key_with_all_names( keyblock, 0, 0, 1, 0 );
787 if( edit_ownertrust( find_kbnode( keyblock,
788 PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
790 /* we don't need to set modified here, as the trustvalues
791 * are updated immediately */
795 show_key_with_all_names( keyblock, 0, 0, 0, 1 );
803 tty_printf(_("Invalid command (try \"help\")\n"));
806 } /* end main loop */
809 release_kbnode( keyblock );
810 release_kbnode( sec_keyblock );
816 * show preferences of a public keyblock.
819 show_prefs( KBNODE keyblock, PKT_user_id *uid )
821 KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
829 return; /* is a secret keyblock */
830 pk = node->pkt->pkt.public_key;
831 if( !pk->local_id ) {
832 log_error("oops: no LID\n");
836 rmd160_hash_buffer( namehash, uid->name, uid->len );
838 p = get_pref_data( pk->local_id, namehash, &n );
843 for(i=0; i < n; i+=2 ) {
845 tty_printf( " %c%d", p[i] == PREFTYPE_SYM ? 'S' :
846 p[i] == PREFTYPE_HASH ? 'H' :
847 p[i] == PREFTYPE_COMPR ? 'Z' : '?', p[i+1]);
856 * Display the key a the user ids, if only_marked is true, do only
857 * so for user ids with mark A flag set and dont display the index number
860 show_key_with_all_names( KBNODE keyblock, int only_marked,
861 int with_fpr, int with_subkeys, int with_prefs )
867 for( node = keyblock; node; node = node->next ) {
868 if( node->pkt->pkttype == PKT_PUBLIC_KEY
869 || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
870 PKT_public_key *pk = node->pkt->pkt.public_key;
871 int otrust=0, trust=0;
873 if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
874 /* do it here, so that debug messages don't clutter the
876 trust = query_trust_info(pk);
877 otrust = get_ownertrust_info( pk->local_id );
880 tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
881 node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
882 (node->flag & NODFLG_SELKEY)? '*':' ',
884 pubkey_letter( pk->pubkey_algo ),
885 (ulong)keyid_from_pk(pk,NULL),
887 expirestr_from_pk(pk) );
888 if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
889 tty_printf(" trust: %c/%c", otrust, trust );
892 show_fingerprint( pk );
897 else if( node->pkt->pkttype == PKT_SECRET_KEY
898 || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
899 PKT_secret_key *sk = node->pkt->pkt.secret_key;
900 tty_printf("%s%c %4u%c/%08lX created: %s expires: %s\n",
901 node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
902 (node->flag & NODFLG_SELKEY)? '*':' ',
904 pubkey_letter( sk->pubkey_algo ),
905 (ulong)keyid_from_sk(sk,NULL),
907 expirestr_from_sk(sk) );
912 for( node = keyblock; node; node = node->next ) {
913 if( node->pkt->pkttype == PKT_USER_ID ) {
914 PKT_user_id *uid = node->pkt->pkt.user_id;
916 if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
919 else if( node->flag & NODFLG_SELUID )
920 tty_printf("(%d)* ", i);
922 tty_printf("(%d) ", i);
923 tty_print_string( uid->name, uid->len );
926 show_prefs( keyblock, uid );
933 show_key_and_fingerprint( KBNODE keyblock )
936 PKT_public_key *pk = NULL;
938 for( node = keyblock; node; node = node->next ) {
939 if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
940 pk = node->pkt->pkt.public_key;
941 tty_printf("pub %4u%c/%08lX %s ",
943 pubkey_letter( pk->pubkey_algo ),
944 (ulong)keyid_from_pk(pk,NULL),
945 datestr_from_pk(pk) );
947 else if( node->pkt->pkttype == PKT_USER_ID ) {
948 PKT_user_id *uid = node->pkt->pkt.user_id;
949 tty_print_string( uid->name, uid->len );
955 show_fingerprint( pk );
960 show_fingerprint( PKT_public_key *pk )
962 byte array[MAX_FINGERPRINT_LEN], *p;
965 fingerprint_from_pk( pk, array, &n );
967 tty_printf(" Fingerprint:");
969 for(i=0; i < n ; i++, i++, p += 2 ) {
972 tty_printf(" %02X%02X", *p, p[1] );
976 for(i=0; i < n ; i++, p++ ) {
979 tty_printf(" %02X", *p );
987 * Ask for a new user id , do the selfsignature and put it into
989 * Return true if there is a new user id
992 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
995 PKT_public_key *pk=NULL;
996 PKT_secret_key *sk=NULL;
997 PKT_signature *sig=NULL;
1000 KBNODE pub_where=NULL, sec_where=NULL;
1003 uid = generate_user_id();
1007 for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1008 if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1009 pk = node->pkt->pkt.public_key;
1010 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1013 if( !node ) /* no subkey */
1015 for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1016 if( node->pkt->pkttype == PKT_SECRET_KEY )
1017 sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1018 else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1021 if( !node ) /* no subkey */
1025 rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
1026 keygen_add_std_prefs, sk );
1027 free_secret_key( sk );
1029 log_error("signing failed: %s\n", g10_errstr(rc) );
1034 /* insert/append to secret keyblock */
1035 pkt = m_alloc_clear( sizeof *pkt );
1036 pkt->pkttype = PKT_USER_ID;
1037 pkt->pkt.user_id = copy_user_id(NULL, uid);
1038 node = new_kbnode(pkt);
1040 insert_kbnode( sec_where, node, 0 );
1042 add_kbnode( sec_keyblock, node );
1043 pkt = m_alloc_clear( sizeof *pkt );
1044 pkt->pkttype = PKT_SIGNATURE;
1045 pkt->pkt.signature = copy_signature(NULL, sig);
1047 insert_kbnode( node, new_kbnode(pkt), 0 );
1049 add_kbnode( sec_keyblock, new_kbnode(pkt) );
1050 /* insert/append to public keyblock */
1051 pkt = m_alloc_clear( sizeof *pkt );
1052 pkt->pkttype = PKT_USER_ID;
1053 pkt->pkt.user_id = uid;
1054 node = new_kbnode(pkt);
1056 insert_kbnode( pub_where, node, 0 );
1058 add_kbnode( pub_keyblock, node );
1059 pkt = m_alloc_clear( sizeof *pkt );
1060 pkt->pkttype = PKT_SIGNATURE;
1061 pkt->pkt.signature = copy_signature(NULL, sig);
1063 insert_kbnode( node, new_kbnode(pkt), 0 );
1065 add_kbnode( pub_keyblock, new_kbnode(pkt) );
1071 * Remove all selceted userids from the keyrings
1074 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
1079 for( node = pub_keyblock; node; node = node->next ) {
1080 if( node->pkt->pkttype == PKT_USER_ID ) {
1081 selected = node->flag & NODFLG_SELUID;
1083 delete_kbnode( node );
1084 if( sec_keyblock ) {
1087 PKT_user_id *uid = node->pkt->pkt.user_id;
1088 for( snode = sec_keyblock; snode; snode = snode->next ) {
1089 if( snode->pkt->pkttype == PKT_USER_ID ) {
1090 PKT_user_id *suid = snode->pkt->pkt.user_id;
1093 (uid->len == suid->len
1094 && !memcmp( uid->name, suid->name, uid->len));
1096 delete_kbnode( snode );
1099 && snode->pkt->pkttype == PKT_SIGNATURE )
1100 delete_kbnode( snode );
1101 else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
1107 else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1108 delete_kbnode( node );
1109 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1112 commit_kbnode( &pub_keyblock );
1114 commit_kbnode( &sec_keyblock );
1119 * Remove some of the secondary keys
1122 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
1127 for( node = pub_keyblock; node; node = node->next ) {
1128 if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1129 selected = node->flag & NODFLG_SELKEY;
1131 delete_kbnode( node );
1132 if( sec_keyblock ) {
1137 keyid_from_pk( node->pkt->pkt.public_key, ki );
1138 for( snode = sec_keyblock; snode; snode = snode->next ) {
1139 if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1142 keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
1143 s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
1145 delete_kbnode( snode );
1148 && snode->pkt->pkttype == PKT_SIGNATURE )
1149 delete_kbnode( snode );
1156 else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
1157 delete_kbnode( node );
1161 commit_kbnode( &pub_keyblock );
1163 commit_kbnode( &sec_keyblock );
1169 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
1174 PKT_secret_key *sk; /* copy of the main sk */
1175 PKT_public_key *main_pk, *sub_pk;
1180 if( count_selected_keys( sec_keyblock ) ) {
1181 tty_printf(_("Please remove selections from the secret keys.\n"));
1185 n1 = count_selected_keys( pub_keyblock );
1187 tty_printf(_("Please select at most one secondary key.\n"));
1191 tty_printf(_("Changing exiration time for a secondary key.\n"));
1193 tty_printf(_("Changing exiration time for the primary key.\n"));
1197 expiredate = ask_expiredate();
1198 /* fixme: check that expiredate is > key creation date */
1200 /* get the secret key , make a copy and set the expiration time into
1201 * that key (because keygen_add-key-expire expects it there)
1203 node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
1204 sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1205 sk->expiredate = expiredate;
1207 /* Now we can actually change the self signature(s) */
1208 main_pk = sub_pk = NULL;
1210 for( node=pub_keyblock; node; node = node->next ) {
1211 if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1212 main_pk = node->pkt->pkt.public_key;
1213 keyid_from_pk( main_pk, keyid );
1215 else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1216 && (node->flag & NODFLG_SELKEY ) )
1217 sub_pk = node->pkt->pkt.public_key;
1218 else if( node->pkt->pkttype == PKT_USER_ID )
1219 uid = node->pkt->pkt.user_id;
1220 else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
1221 PKT_signature *sig = node->pkt->pkt.signature;
1222 if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
1223 && ( (mainkey && uid && (sig->sig_class&~3) == 0x10)
1224 || (!mainkey && sig->sig_class == 0x18) ) ) {
1225 /* this is a selfsignature which should be replaced */
1226 PKT_signature *newsig;
1230 /* find the corresponding secret self-signature */
1231 for( sn=sec_keyblock; sn; sn = sn->next ) {
1232 if( sn->pkt->pkttype == PKT_SIGNATURE
1233 && !cmp_signatures( sn->pkt->pkt.signature, sig ) )
1237 log_info(_("No corresponding signature in secret ring\n"));
1239 /* create new self signature */
1241 rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
1243 keygen_add_std_prefs, sk );
1245 rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
1247 keygen_add_key_expire, sk );
1249 log_error("make_keysig_packet failed: %s\n",
1251 free_secret_key( sk );
1254 /* replace the packet */
1255 newpkt = m_alloc_clear( sizeof *newpkt );
1256 newpkt->pkttype = PKT_SIGNATURE;
1257 newpkt->pkt.signature = newsig;
1258 free_packet( node->pkt );
1259 m_free( node->pkt );
1262 newpkt = m_alloc_clear( sizeof *newpkt );
1263 newpkt->pkttype = PKT_SIGNATURE;
1264 newpkt->pkt.signature = copy_signature( NULL, newsig );
1265 free_packet( sn->pkt );
1273 free_secret_key( sk );
1279 * Select one user id or remove all selection if index is 0.
1280 * Returns: True if the selection changed;
1283 menu_select_uid( KBNODE keyblock, int index )
1288 /* first check that the index is valid */
1290 for( i=0, node = keyblock; node; node = node->next ) {
1291 if( node->pkt->pkttype == PKT_USER_ID ) {
1297 tty_printf(_("No user id with index %d\n"), index );
1301 else { /* reset all */
1302 for( i=0, node = keyblock; node; node = node->next ) {
1303 if( node->pkt->pkttype == PKT_USER_ID )
1304 node->flag &= ~NODFLG_SELUID;
1308 /* and toggle the new index */
1309 for( i=0, node = keyblock; node; node = node->next ) {
1310 if( node->pkt->pkttype == PKT_USER_ID ) {
1312 if( (node->flag & NODFLG_SELUID) )
1313 node->flag &= ~NODFLG_SELUID;
1315 node->flag |= NODFLG_SELUID;
1323 * Select secondary keys
1324 * Returns: True if the selection changed;
1327 menu_select_key( KBNODE keyblock, int index )
1332 /* first check that the index is valid */
1334 for( i=0, node = keyblock; node; node = node->next ) {
1335 if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1336 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1342 tty_printf(_("No secondary key with index %d\n"), index );
1346 else { /* reset all */
1347 for( i=0, node = keyblock; node; node = node->next ) {
1348 if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1349 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
1350 node->flag &= ~NODFLG_SELKEY;
1354 /* and set the new index */
1355 for( i=0, node = keyblock; node; node = node->next ) {
1356 if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1357 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
1359 if( (node->flag & NODFLG_SELKEY) )
1360 node->flag &= ~NODFLG_SELKEY;
1362 node->flag |= NODFLG_SELKEY;
1371 count_uids_with_flag( KBNODE keyblock, unsigned flag )
1376 for( node = keyblock; node; node = node->next )
1377 if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
1383 count_keys_with_flag( KBNODE keyblock, unsigned flag )
1388 for( node = keyblock; node; node = node->next )
1389 if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
1390 || node->pkt->pkttype == PKT_SECRET_SUBKEY)
1391 && (node->flag & flag) )
1397 count_uids( KBNODE keyblock )
1402 for( node = keyblock; node; node = node->next )
1403 if( node->pkt->pkttype == PKT_USER_ID )
1410 * Returns true if there is at least one selected user id
1413 count_selected_uids( KBNODE keyblock )
1415 return count_uids_with_flag( keyblock, NODFLG_SELUID);
1419 count_selected_keys( KBNODE keyblock )
1421 return count_keys_with_flag( keyblock, NODFLG_SELKEY);