* keygen.c (set_one_pref, keygen_set_std_prefs): Allow using the full
[gnupg.git] / g10 / keyedit.c
1 /* keyedit.c - keyedit stuff
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <ctype.h>
28
29 #include "options.h"
30 #include "packet.h"
31 #include "errors.h"
32 #include "iobuf.h"
33 #include "keydb.h"
34 #include "memory.h"
35 #include "photoid.h"
36 #include "util.h"
37 #include "main.h"
38 #include "trustdb.h"
39 #include "filter.h"
40 #include "ttyio.h"
41 #include "status.h"
42 #include "i18n.h"
43
44 static void show_prefs( PKT_user_id *uid, int verbose );
45 static void show_key_with_all_names( KBNODE keyblock, int only_marked,
46             int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
47 static void show_key_and_fingerprint( KBNODE keyblock );
48 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock, int photo );
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_addrevoker( KBNODE pub_keyblock,
53                             KBNODE sec_keyblock, int sensitive );
54 static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
55 static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
56 static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
57 static int menu_select_uid( KBNODE keyblock, int idx );
58 static int menu_select_key( KBNODE keyblock, int idx );
59 static int count_uids( KBNODE keyblock );
60 static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
61 static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
62 static int count_selected_uids( KBNODE keyblock );
63 static int real_uids_left( KBNODE keyblock );
64 static int count_selected_keys( KBNODE keyblock );
65 static int menu_revsig( KBNODE keyblock );
66 static int menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
67 static int enable_disable_key( KBNODE keyblock, int disable );
68 static void menu_showphoto( KBNODE keyblock );
69
70 static int update_trust=0;
71
72 #define CONTROL_D ('D' - 'A' + 1)
73
74 #define NODFLG_BADSIG (1<<0)  /* bad signature */
75 #define NODFLG_NOKEY  (1<<1)  /* no public key */
76 #define NODFLG_SIGERR (1<<2)  /* other sig error */
77
78 #define NODFLG_MARK_A (1<<4)  /* temporary mark */
79 #define NODFLG_DELSIG (1<<5)  /* to be deleted */
80
81 #define NODFLG_SELUID (1<<8)  /* indicate the selected userid */
82 #define NODFLG_SELKEY (1<<9)  /* indicate the selected key */
83 #define NODFLG_SELSIG (1<<10) /* indicate a selected signature */
84
85 struct sign_attrib {
86     int non_exportable,non_revocable;
87     struct revocation_reason_info *reason;
88 };
89
90 /****************
91  * Print information about a signature, check it and return true
92  * if the signature is okay. NODE must be a signature packet.
93  */
94 static int
95 print_and_check_one_sig( KBNODE keyblock, KBNODE node,
96                          int *inv_sigs, int *no_key, int *oth_err,
97                         int *is_selfsig, int print_without_key )
98 {
99     PKT_signature *sig = node->pkt->pkt.signature;
100     int rc, sigrc;
101     int is_rev = sig->sig_class == 0x30;
102
103     /* TODO: Make sure a cached sig record here still has the pk that
104        issued it.  See also keylist.c:list_keyblock_print */
105
106     switch( (rc = check_key_signature( keyblock, node, is_selfsig)) ) {
107       case 0:
108         node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
109         sigrc = '!';
110         break;
111       case G10ERR_BAD_SIGN:
112         node->flag = NODFLG_BADSIG;
113         sigrc = '-';
114         if( inv_sigs )
115             ++*inv_sigs;
116         break;
117       case G10ERR_NO_PUBKEY:
118       case G10ERR_UNU_PUBKEY:
119         node->flag = NODFLG_NOKEY;
120         sigrc = '?';
121         if( no_key )
122             ++*no_key;
123         break;
124       default:
125         node->flag = NODFLG_SIGERR;
126         sigrc = '%';
127         if( oth_err )
128             ++*oth_err;
129         break;
130     }
131     if( sigrc != '?' || print_without_key ) {
132         tty_printf("%s%c%c %c%c%c%c%c%c %08lX %s   ",
133                    is_rev? "rev":"sig",sigrc,
134                    (sig->sig_class-0x10>0 &&
135                     sig->sig_class-0x10<4)?'0'+sig->sig_class-0x10:' ',
136                    sig->flags.exportable?' ':'L',
137                    sig->flags.revocable?' ':'R',
138                    sig->flags.policy_url?'P':' ',
139                    sig->flags.notation?'N':' ',
140                    sig->flags.expired?'X':' ',
141                    (sig->trust_depth>9)?'T':
142                    (sig->trust_depth>0)?'0'+sig->trust_depth:' ',
143                    (ulong)sig->keyid[1], datestr_from_sig(sig));
144         if( sigrc == '%' )
145             tty_printf("[%s] ", g10_errstr(rc) );
146         else if( sigrc == '?' )
147             ;
148         else if( *is_selfsig ) {
149             tty_printf( is_rev? _("[revocation]")
150                               : _("[self-signature]") );
151         }
152         else {
153             size_t n;
154             char *p = get_user_id( sig->keyid, &n );
155             tty_print_utf8_string2( p, n, 40 );
156             m_free(p);
157         }
158         tty_printf("\n");
159
160         if(sig->flags.policy_url && opt.show_policy_url)
161           show_policy_url(sig,3);
162
163         if(sig->flags.notation && opt.show_notation)
164           show_notation(sig,3);
165     }
166
167     return (sigrc == '!');
168 }
169
170
171
172 /****************
173  * Check the keysigs and set the flags to indicate errors.
174  * Returns true if error found.
175  */
176 static int
177 check_all_keysigs( KBNODE keyblock, int only_selected )
178 {
179     KBNODE kbctx;
180     KBNODE node;
181     int inv_sigs = 0;
182     int no_key = 0;
183     int oth_err = 0;
184     int has_selfsig = 0;
185     int mis_selfsig = 0;
186     int selected = !only_selected;
187     int anyuid = 0;
188
189     for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
190         if( node->pkt->pkttype == PKT_USER_ID ) {
191             PKT_user_id *uid = node->pkt->pkt.user_id;
192
193             if( only_selected )
194                 selected = (node->flag & NODFLG_SELUID);
195             if( selected ) {
196                 tty_printf("uid  ");
197                 tty_print_utf8_string( uid->name, uid->len );
198                 tty_printf("\n");
199                 if( anyuid && !has_selfsig )
200                     mis_selfsig++;
201                 has_selfsig = 0;
202                 anyuid = 1;
203             }
204         }
205         else if( selected && node->pkt->pkttype == PKT_SIGNATURE
206                  && ( (node->pkt->pkt.signature->sig_class&~3) == 0x10
207                      || node->pkt->pkt.signature->sig_class == 0x30 )  ) {
208             int selfsig;
209
210             if( print_and_check_one_sig( keyblock, node, &inv_sigs,
211                                         &no_key, &oth_err, &selfsig, 0 ) ) {
212                 if( selfsig )
213                     has_selfsig = 1;
214             }
215             /* Hmmm: should we update the trustdb here? */
216         }
217     }
218     if( !has_selfsig )
219         mis_selfsig++;
220     if( inv_sigs == 1 )
221         tty_printf(_("1 bad signature\n") );
222     else if( inv_sigs )
223         tty_printf(_("%d bad signatures\n"), inv_sigs );
224     if( no_key == 1 )
225         tty_printf(_("1 signature not checked due to a missing key\n") );
226     else if( no_key )
227         tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
228     if( oth_err == 1 )
229         tty_printf(_("1 signature not checked due to an error\n") );
230     else if( oth_err )
231         tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
232     if( mis_selfsig == 1 )
233         tty_printf(_("1 user ID without valid self-signature detected\n"));
234     else if( mis_selfsig  )
235         tty_printf(_("%d user IDs without valid self-signatures detected\n"),
236                                                                     mis_selfsig);
237
238     return inv_sigs || no_key || oth_err || mis_selfsig;
239 }
240
241
242
243
244 static int
245 sign_mk_attrib( PKT_signature *sig, void *opaque )
246 {
247     struct sign_attrib *attrib = opaque;
248     byte buf[8];
249
250     if( attrib->non_exportable ) {
251         buf[0] = 0; /* not exportable */
252         build_sig_subpkt( sig, SIGSUBPKT_EXPORTABLE, buf, 1 );
253     }
254
255     if( attrib->non_revocable ) {
256         buf[0] = 0; /* not revocable */
257         build_sig_subpkt( sig, SIGSUBPKT_REVOCABLE, buf, 1 );
258     }
259
260     if( attrib->reason )
261         revocation_reason_build_cb( sig, attrib->reason );
262
263     return 0;
264 }
265
266
267
268 /****************
269  * Loop over all locusr and and sign the uids after asking.
270  * If no user id is marked, all user ids will be signed;
271  * if some user_ids are marked those will be signed.
272  */
273 static int
274 sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified,
275            int local , int nonrevocable )
276 {
277     int rc = 0;
278     SK_LIST sk_list = NULL;
279     SK_LIST sk_rover = NULL;
280     PKT_secret_key *sk = NULL;
281     KBNODE node, uidnode;
282     PKT_public_key *primary_pk=NULL;
283     int select_all = !count_selected_uids(keyblock);
284     int all_v3=1;
285
286     /* Are there any non-v3 sigs on this key already? */
287     if(opt.pgp2)
288       for(node=keyblock;node;node=node->next)
289         if(node->pkt->pkttype==PKT_SIGNATURE &&
290            node->pkt->pkt.signature->version>3)
291           {
292             all_v3=0;
293             break;
294           }
295
296     /* build a list of all signators.
297      *    
298      * We use the CERT flag to request the primary which must always
299      * be one which is capable of signing keys.  I can't see a reason
300      * why to sign keys using a subkey.  Implementation of USAGE_CERT
301      * is just a hack in getkey.c and does not mean that a subkey
302      * marked as certification capable will be used */
303     rc=build_sk_list( locusr, &sk_list, 0, PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT);
304     if( rc )
305         goto leave;
306
307     /* loop over all signators */
308     for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
309         u32 sk_keyid[2],pk_keyid[2];
310         size_t n;
311         char *p;
312         int force_v4=0,class=0,selfsig=0;
313         u32 duration=0,timestamp=0;
314
315         if(local || nonrevocable ||
316            opt.cert_policy_url || opt.cert_notation_data)
317           force_v4=1;
318
319         /* we have to use a copy of the sk, because make_keysig_packet
320          * may remove the protection from sk and if we did other
321          * changes to the secret key, we would save the unprotected
322          * version */
323         if( sk )
324             free_secret_key(sk);
325         sk = copy_secret_key( NULL, sk_rover->sk );
326         keyid_from_sk( sk, sk_keyid );
327         /* set mark A for all selected user ids */
328         for( node=keyblock; node; node = node->next ) {
329             if( select_all || (node->flag & NODFLG_SELUID) )
330                 node->flag |= NODFLG_MARK_A;
331             else
332                 node->flag &= ~NODFLG_MARK_A;
333         }
334         /* reset mark for uids which are already signed */
335         uidnode = NULL;
336         for( node=keyblock; node; node = node->next ) {
337             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
338                 primary_pk=node->pkt->pkt.public_key;
339                 keyid_from_pk( primary_pk, pk_keyid );
340
341                 /* Is this a self-sig? */
342                 if(pk_keyid[0]==sk_keyid[0] && pk_keyid[1]==sk_keyid[1])
343                   {
344                     selfsig=1;
345                     /* Do not force a v4 sig here, otherwise it would
346                        be difficult to remake a v3 selfsig.  If this
347                        is a v3->v4 promotion case, then we set
348                        force_v4 later anyway. */
349                     force_v4=0;
350                   }
351             }
352             else if( node->pkt->pkttype == PKT_USER_ID ) {
353                 uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
354                 if(uidnode)
355                   {
356                     char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
357                                               uidnode->pkt->pkt.user_id->len,
358                                               0);
359
360                     if(uidnode->pkt->pkt.user_id->is_revoked)
361                       {
362                         tty_printf(_("User ID \"%s\" is revoked."),user);
363
364                         if(opt.expert)
365                           {
366                             tty_printf("\n");
367                             /* No, so remove the mark and continue */
368                             if(!cpr_get_answer_is_yes("sign_uid.revoke_okay",
369                                                       _("Are you sure you "
370                                                         "still want to sign "
371                                                         "it? (y/N) ")))
372                               uidnode->flag &= ~NODFLG_MARK_A;
373                           }
374                         else
375                           {
376                             uidnode->flag &= ~NODFLG_MARK_A;
377                             tty_printf(_("  Unable to sign.\n"));
378                           }
379                       }
380                     else if(!uidnode->pkt->pkt.user_id->created)
381                       {
382                         tty_printf(_("WARNING: user ID \"%s\" is not "
383                                      "self-signed.\n"),user);
384                       }
385
386                     m_free(user);
387                   }
388             }
389             else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
390                 && (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
391                 if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
392                     && sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
393                     char buf[50];
394                     char *user=utf8_to_native(uidnode->pkt->pkt.user_id->name,
395                                               uidnode->pkt->pkt.user_id->len,
396                                               0);
397
398                     /* It's a v3 self-sig.  Make it into a v4 self-sig? */
399                     if(node->pkt->pkt.signature->version<4 && selfsig)
400                       {
401                         tty_printf(_("The self-signature on \"%s\"\n"
402                                      "is a PGP 2.x-style signature.\n"),user);
403  
404                         /* Note that the regular PGP2 warning below
405                            still applies if there are no v4 sigs on
406                            this key at all. */
407
408                         if(opt.expert)
409                           if(cpr_get_answer_is_yes("sign_uid.v4_promote_okay",
410                                                    _("Do you want to promote "
411                                                      "it to an OpenPGP self-"
412                                                      "signature? (y/N) ")))
413                             {
414                               force_v4=1;
415                               node->flag|=NODFLG_DELSIG;
416                               continue;
417                             }
418                       }
419
420                     if(!node->pkt->pkt.signature->flags.exportable && !local)
421                       {
422                         /* It's a local sig, and we want to make a
423                            exportable sig. */
424                         tty_printf(_("Your current signature on \"%s\"\n"
425                                      "is a local signature.\n"),user);
426
427                         if(cpr_get_answer_is_yes("sign_uid.local_promote_okay",
428                                                  _("Do you want to promote "
429                                                    "it to a full exportable "
430                                                    "signature? (y/N) ")))
431                           {
432                             /* Mark these for later deletion.  We
433                                don't want to delete them here, just in
434                                case the replacement signature doesn't
435                                happen for some reason.  We only delete
436                                these after the replacement is already
437                                in place. */
438
439                             node->flag|=NODFLG_DELSIG;
440                             continue;
441                           }
442                       }
443
444                     /* Fixme: see whether there is a revocation in which
445                      * case we should allow to sign it again. */
446                     if (!node->pkt->pkt.signature->flags.exportable && local)
447                       tty_printf(_(
448                          "\"%s\" was already locally signed by key %08lX\n"),
449                                  user,(ulong)sk_keyid[1] );
450                     else
451                       tty_printf(_(
452                          "\"%s\" was already signed by key %08lX\n"),
453                                  user,(ulong)sk_keyid[1] );
454                     sprintf (buf, "%08lX%08lX",
455                              (ulong)sk->keyid[0], (ulong)sk->keyid[1] );
456                     write_status_text (STATUS_ALREADY_SIGNED, buf);
457                     uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
458
459                     m_free(user);
460                 }
461             }
462         }
463         /* check whether any uids are left for signing */
464         if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
465             tty_printf(_("Nothing to sign with key %08lX\n"),
466                                                   (ulong)sk_keyid[1] );
467             continue;
468         }
469         /* Ask whether we really should sign these user id(s) */
470         tty_printf("\n");
471         show_key_with_all_names( keyblock, 1, 0, 1, 0, 0 );
472         tty_printf("\n");
473
474         if(primary_pk->expiredate && !selfsig)
475           {
476             u32 now=make_timestamp();
477
478             if(primary_pk->expiredate<=now)
479               {
480                 tty_printf(_("This key has expired!"));
481
482                 if(opt.expert)
483                   {
484                     tty_printf("  ");
485                     if(!cpr_get_answer_is_yes("sign_uid.expired_okay",
486                                               _("Are you sure you still "
487                                                 "want to sign it? (y/N) ")))
488                       continue;
489                   }
490                 else
491                   {
492                     tty_printf(_("  Unable to sign.\n"));
493                     continue;
494                   }
495               }
496             else
497               {
498                 char *answer;
499
500                 tty_printf(_("This key is due to expire on %s.\n"),
501                            expirestr_from_pk(primary_pk));
502
503                 answer=cpr_get("sign_uid.expire",
504                                _("Do you want your signature to "
505                                  "expire at the same time? (Y/n) "));
506                 if(answer_is_yes_no_default(answer,1))
507                   {
508                     /* This fixes the signature timestamp we're going
509                        to make as now.  This is so the expiration date
510                        is exactly correct, and not a few seconds off
511                        (due to the time it takes to answer the
512                        questions, enter the passphrase, etc). */
513                     timestamp=now;
514                     duration=primary_pk->expiredate-now;
515                     force_v4=1;
516                   }
517
518                 cpr_kill_prompt();
519                 m_free(answer);
520               }
521           }
522
523         /* Only ask for duration if we haven't already set it to match
524            the expiration of the pk */
525         if(opt.ask_cert_expire && !duration && !selfsig)
526           duration=ask_expire_interval(1);
527
528         if(duration)
529           force_v4=1;
530
531         /* Is --pgp2 on, it's a v3 key, all the sigs on the key are
532            currently v3 and we're about to sign it with a v4 sig?  If
533            so, danger! */
534         if(opt.pgp2 && all_v3 &&
535            (sk->version>3 || force_v4) && primary_pk->version<=3)
536           {
537             tty_printf(_("You may not make an OpenPGP signature on a "
538                          "PGP 2.x key while in --pgp2 mode.\n"));
539             tty_printf(_("This would make the key unusable in PGP 2.x.\n"));
540
541             if(opt.expert)
542               {
543                 if(!cpr_get_answer_is_yes("sign_uid.v4_on_v3_okay",
544                                           _("Are you sure you still "
545                                             "want to sign it? (y/N) ")))
546                   continue;
547
548                 all_v3=0;
549               }
550             else
551               continue;
552           }
553
554         if(selfsig)
555           ;
556         else if(opt.batch)
557           class=0x10+opt.def_cert_check_level;
558         else
559           {
560             char *answer;
561
562             tty_printf(_("How carefully have you verified the key you are "
563                          "about to sign actually belongs\nto the person named "
564                          "above?  If you don't know what to answer, enter \"0\".\n"));
565             tty_printf("\n");
566             tty_printf(_("   (0) I will not answer.%s\n"),
567                        opt.def_cert_check_level==0?_(" (default)"):"");
568             tty_printf(_("   (1) I have not checked at all.%s\n"),
569                        opt.def_cert_check_level==1?_(" (default)"):"");
570             tty_printf(_("   (2) I have done casual checking.%s\n"),
571                        opt.def_cert_check_level==2?_(" (default)"):"");
572             tty_printf(_("   (3) I have done very careful checking.%s\n"),
573                        opt.def_cert_check_level==3?_(" (default)"):"");
574             tty_printf("\n");
575
576             while(class==0)
577               {
578                 answer = cpr_get("sign_uid.class",_("Your selection? "));
579
580                 if(answer[0]=='\0')
581                   class=0x10+opt.def_cert_check_level; /* Default */
582                 else if(ascii_strcasecmp(answer,"0")==0)
583                   class=0x10; /* Generic */
584                 else if(ascii_strcasecmp(answer,"1")==0)
585                   class=0x11; /* Persona */
586                 else if(ascii_strcasecmp(answer,"2")==0)
587                   class=0x12; /* Casual */
588                 else if(ascii_strcasecmp(answer,"3")==0)
589                   class=0x13; /* Positive */
590                 else
591                   tty_printf(_("Invalid selection.\n"));
592
593                 m_free(answer);
594               }
595           }
596
597         tty_printf(_("Are you really sure that you want to sign this key\n"
598                      "with your key: \""));
599         p = get_user_id( sk_keyid, &n );
600         tty_print_utf8_string( p, n );
601         m_free(p); p = NULL;
602         tty_printf("\"\n");
603
604         if(selfsig)
605           {
606             tty_printf(_("\nThis will be a self-signature.\n"));
607
608             if( local )
609               tty_printf(
610                          _("\nWARNING: the signature will not be marked "
611                            "as non-exportable.\n"));
612
613             if( nonrevocable )
614               tty_printf(
615                          _("\nWARNING: the signature will not be marked "
616                            "as non-revocable.\n"));
617           }
618         else
619           {
620             if( local )
621               tty_printf(
622                      _("\nThe signature will be marked as non-exportable.\n"));
623
624             if( nonrevocable )
625               tty_printf(
626                       _("\nThe signature will be marked as non-revocable.\n"));
627
628             switch(class)
629               {
630               case 0x11:
631                 tty_printf(_("\nI have not checked this key at all.\n"));
632                 break;
633
634               case 0x12:
635                 tty_printf(_("\nI have checked this key casually.\n"));
636                 break;
637
638               case 0x13:
639                 tty_printf(_("\nI have checked this key very carefully.\n"));
640                 break;
641               }
642           }
643
644         tty_printf("\n");
645
646         if( opt.batch && opt.answer_yes )
647           ;
648         else if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
649             continue;
650
651         /* now we can sign the user ids */
652       reloop: /* (must use this, because we are modifing the list) */
653         primary_pk = NULL;
654         for( node=keyblock; node; node = node->next ) {
655             if( node->pkt->pkttype == PKT_PUBLIC_KEY )
656                 primary_pk = node->pkt->pkt.public_key;
657             else if( node->pkt->pkttype == PKT_USER_ID
658                      && (node->flag & NODFLG_MARK_A) ) {
659                 PACKET *pkt;
660                 PKT_signature *sig;
661                 struct sign_attrib attrib;
662
663                 assert( primary_pk );
664                 memset( &attrib, 0, sizeof attrib );
665                 attrib.non_exportable = local;
666                 attrib.non_revocable = nonrevocable;
667                 node->flag &= ~NODFLG_MARK_A;
668
669                 /* we force creation of a v4 signature for local
670                  * signatures, otherwise we would not generate the
671                  * subpacket with v3 keys and the signature becomes
672                  * exportable */
673
674                 if(selfsig)
675                   rc = make_keysig_packet( &sig, primary_pk,
676                                            node->pkt->pkt.user_id,
677                                            NULL,
678                                            sk,
679                                            0x13, 0, force_v4?4:0, 0, 0,
680                                            keygen_add_std_prefs, primary_pk);
681                 else
682                   rc = make_keysig_packet( &sig, primary_pk,
683                                            node->pkt->pkt.user_id,
684                                            NULL,
685                                            sk,
686                                            class, 0, force_v4?4:0,
687                                            timestamp, duration,
688                                            sign_mk_attrib, &attrib );
689                 if( rc ) {
690                     log_error(_("signing failed: %s\n"), g10_errstr(rc));
691                     goto leave;
692                 }
693
694                 *ret_modified = 1; /* we changed the keyblock */
695                 update_trust = 1;
696
697                 pkt = m_alloc_clear( sizeof *pkt );
698                 pkt->pkttype = PKT_SIGNATURE;
699                 pkt->pkt.signature = sig;
700                 insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
701                 goto reloop;
702             }
703         }
704
705         /* Delete any sigs that got promoted */
706         for( node=keyblock; node; node = node->next )
707           if( node->flag & NODFLG_DELSIG)
708             delete_kbnode(node);
709     } /* end loop over signators */
710
711   leave:
712     release_sk_list( sk_list );
713     if( sk )
714         free_secret_key(sk);
715     return rc;
716 }
717
718
719
720 /****************
721  * Change the passphrase of the primary and all secondary keys.
722  * We use only one passphrase for all keys.
723  */
724 static int
725 change_passphrase( KBNODE keyblock )
726 {
727     int rc = 0;
728     int changed=0;
729     KBNODE node;
730     PKT_secret_key *sk;
731     char *passphrase = NULL;
732     int no_primary_secrets = 0;
733
734     node = find_kbnode( keyblock, PKT_SECRET_KEY );
735     if( !node ) {
736         log_error("Oops; secret key not found anymore!\n");
737         goto leave;
738     }
739     sk = node->pkt->pkt.secret_key;
740
741     switch( is_secret_key_protected( sk ) ) {
742       case -1:
743         rc = G10ERR_PUBKEY_ALGO;
744         break;
745       case 0:
746         tty_printf(_("This key is not protected.\n"));
747         break;
748       default:
749         if( sk->protect.s2k.mode == 1001 ) {
750             tty_printf(_("Secret parts of primary key are not available.\n"));
751             no_primary_secrets = 1;
752         }
753         else {
754             tty_printf(_("Key is protected.\n"));
755             rc = check_secret_key( sk, 0 );
756             if( !rc )
757                 passphrase = get_last_passphrase();
758         }
759         break;
760     }
761
762     /* unprotect all subkeys (use the supplied passphrase or ask)*/
763     for(node=keyblock; !rc && node; node = node->next ) {
764         if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
765             PKT_secret_key *subsk = node->pkt->pkt.secret_key;
766             set_next_passphrase( passphrase );
767             rc = check_secret_key( subsk, 0 );
768             if( !rc && !passphrase )
769                 passphrase = get_last_passphrase();
770         }
771     }
772
773     if( rc )
774         tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
775     else {
776         DEK *dek = NULL;
777         STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
778         const char *errtext = NULL;
779
780         tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
781
782         set_next_passphrase( NULL );
783         for(;;) {
784             s2k->mode = opt.s2k_mode;
785             s2k->hash_algo = opt.s2k_digest_algo;
786             dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo,
787                                      s2k, 2, errtext);
788             if( !dek ) {
789                 errtext = _("passphrase not correctly repeated; try again");
790                 tty_printf ("%s.\n", errtext);
791             }
792             else if( !dek->keylen ) {
793                 rc = 0;
794                 tty_printf(_( "You don't want a passphrase -"
795                             " this is probably a *bad* idea!\n\n"));
796                 if( cpr_get_answer_is_yes("change_passwd.empty.okay",
797                                _("Do you really want to do this? ")))
798                     changed++;
799                 break;
800             }
801             else { /* okay */
802                 rc = 0;
803                 if( !no_primary_secrets ) {
804                     sk->protect.algo = dek->algo;
805                     sk->protect.s2k = *s2k;
806                     rc = protect_secret_key( sk, dek );
807                 }
808                 for(node=keyblock; !rc && node; node = node->next ) {
809                     if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
810                         PKT_secret_key *subsk = node->pkt->pkt.secret_key;
811                         subsk->protect.algo = dek->algo;
812                         subsk->protect.s2k = *s2k;
813                         rc = protect_secret_key( subsk, dek );
814                     }
815                 }
816                 if( rc )
817                     log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
818                 else
819                     changed++;
820                 break;
821             }
822         }
823         m_free(s2k);
824         m_free(dek);
825     }
826
827   leave:
828     m_free( passphrase );
829     set_next_passphrase( NULL );
830     return changed && !rc;
831 }
832
833
834 /****************
835  * There are some keys out (due to a bug in gnupg), where the sequence
836  * of the packets is wrong.  This function fixes that.
837  * Returns: true if the keyblock has been fixed.
838  *
839  * Note:  This function does not work if there is more than one user ID.
840  */
841 static int
842 fix_keyblock( KBNODE keyblock )
843 {
844     KBNODE node, last, subkey;
845     int fixed=0;
846
847     /* locate key signatures of class 0x10..0x13 behind sub key packets */
848     for( subkey=last=NULL, node = keyblock; node;
849                                             last=node, node = node->next ) {
850         switch( node->pkt->pkttype ) {
851           case PKT_PUBLIC_SUBKEY:
852           case PKT_SECRET_SUBKEY:
853             if( !subkey )
854                 subkey = last; /* actually it is the one before the subkey */
855             break;
856           case PKT_SIGNATURE:
857             if( subkey ) {
858                 PKT_signature *sig = node->pkt->pkt.signature;
859                 if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
860                     log_info(_(
861                         "moving a key signature to the correct place\n"));
862                     last->next = node->next;
863                     node->next = subkey->next;
864                     subkey->next = node;
865                     node = last;
866                     fixed=1;
867                 }
868             }
869             break;
870           default: break;
871         }
872     }
873
874     return fixed;
875 }
876
877 /****************
878  * Menu driven key editor.  If sign_mode is true semi-automatical signing
879  * will be performed. commands are ignore in this case
880  *
881  * Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
882  */
883
884 void
885 keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
886                                                     int sign_mode )
887 {
888     enum cmdids { cmdNONE = 0,
889            cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
890            cmdLSIGN, cmdNRSIGN, cmdNRLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG,
891            cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID,
892            cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY,
893            cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE, cmdENABLEKEY,
894            cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF, cmdINVCMD,
895            cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST, cmdNOP };
896     static struct { const char *name;
897                     enum cmdids id;
898                     int need_sk;
899                     int not_with_sk;
900                     int signmode;
901                     const char *desc;
902                   } cmds[] = {
903         { N_("quit")    , cmdQUIT      , 0,0,1, N_("quit this menu") },
904         { N_("q")       , cmdQUIT      , 0,0,1, NULL   },
905         { N_("save")    , cmdSAVE      , 0,0,1, N_("save and quit") },
906         { N_("help")    , cmdHELP      , 0,0,1, N_("show this help") },
907         {    "?"        , cmdHELP      , 0,0,1, NULL   },
908         { N_("fpr")     , cmdFPR       , 0,0,1, N_("show fingerprint") },
909         { N_("list")    , cmdLIST      , 0,0,1, N_("list key and user IDs") },
910         { N_("l")       , cmdLIST      , 0,0,1, NULL   },
911         { N_("uid")     , cmdSELUID    , 0,0,1, N_("select user ID N") },
912         { N_("key")     , cmdSELKEY    , 0,0,0, N_("select secondary key N") },
913         { N_("check")   , cmdCHECK     , 0,0,1, N_("list signatures") },
914         { N_("c")       , cmdCHECK     , 0,0,1, NULL },
915         { N_("sign")    , cmdSIGN      , 0,1,1, N_("sign the key") },
916         { N_("s")       , cmdSIGN      , 0,1,1, NULL },
917         { N_("lsign")   , cmdLSIGN     , 0,1,1, N_("sign the key locally") },
918         { N_("nrsign")  , cmdNRSIGN    , 0,1,1, N_("sign the key non-revocably") },
919         { N_("nrlsign") , cmdNRLSIGN   , 0,1,1, N_("sign the key locally and non-revocably") },
920         { N_("debug")   , cmdDEBUG     , 0,0,0, NULL },
921         { N_("adduid")  , cmdADDUID    , 1,1,0, N_("add a user ID") },
922         { N_("addphoto"), cmdADDPHOTO  , 1,1,0, N_("add a photo ID") },
923         { N_("deluid")  , cmdDELUID    , 0,1,0, N_("delete user ID") },
924         /* delphoto is really deluid in disguise */
925         { N_("delphoto"), cmdDELUID    , 0,1,0, NULL },
926         { N_("addkey")  , cmdADDKEY    , 1,1,0, N_("add a secondary key") },
927         { N_("delkey")  , cmdDELKEY    , 0,1,0, N_("delete a secondary key") },
928         { N_("addrevoker"),cmdADDREVOKER,1,1,0, N_("add a revocation key") },
929         { N_("delsig")  , cmdDELSIG    , 0,1,0, N_("delete signatures") },
930         { N_("expire")  , cmdEXPIRE    , 1,1,0, N_("change the expire date") },
931         { N_("primary") , cmdPRIMARY   , 1,1,0, N_("flag user ID as primary")},
932         { N_("toggle")  , cmdTOGGLE    , 1,0,0, N_("toggle between secret "
933                                                    "and public key listing") },
934         { N_("t"     )  , cmdTOGGLE    , 1,0,0, NULL },
935         { N_("pref")    , cmdPREF      , 0,1,0, N_("list preferences (expert)") },
936         { N_("showpref"), cmdSHOWPREF  , 0,1,0, N_("list preferences (verbose)") },
937         { N_("setpref") , cmdSETPREF   , 1,1,0, N_("set preference list") },
938         { N_("updpref") , cmdUPDPREF   , 1,1,0, N_("updated preferences") },
939         { N_("passwd")  , cmdPASSWD    , 1,1,0, N_("change the passphrase") },
940         { N_("trust")   , cmdTRUST     , 0,1,0, N_("change the ownertrust") },
941         { N_("revsig")  , cmdREVSIG    , 0,1,0, N_("revoke signatures") },
942         { N_("revkey")  , cmdREVKEY    , 1,1,0, N_("revoke a secondary key") },
943         { N_("disable") , cmdDISABLEKEY, 0,1,0, N_("disable a key") },
944         { N_("enable")  , cmdENABLEKEY , 0,1,0, N_("enable a key") },
945         { N_("showphoto"),cmdSHOWPHOTO , 0,0,0, N_("show photo ID") },
946
947     { NULL, cmdNONE } };
948     enum cmdids cmd = 0;
949     int rc = 0;
950     KBNODE keyblock = NULL;
951     KEYDB_HANDLE kdbhd = NULL;
952     KBNODE sec_keyblock = NULL;
953     KEYDB_HANDLE sec_kdbhd = NULL;
954     KBNODE cur_keyblock;
955     char *answer = NULL;
956     int redisplay = 1;
957     int modified = 0;
958     int sec_modified = 0;
959     int toggle;
960     int have_commands = !!commands;
961
962     if ( opt.command_fd != -1 )
963         ;
964     else if( opt.batch && !have_commands  ) {
965         log_error(_("can't do that in batchmode\n"));
966         goto leave;
967     }
968
969     if( sign_mode ) {
970         commands = NULL;
971         append_to_strlist( &commands, sign_mode == 1? "sign":
972                            sign_mode == 2?"lsign":
973                            sign_mode == 3?"nrsign":"nrlsign");
974         have_commands = 1;
975     }
976
977     /* get the public key */
978     rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd);
979     if( rc )
980         goto leave;
981     if( fix_keyblock( keyblock ) )
982         modified++;
983     if( collapse_uids( &keyblock ) )
984         modified++;
985
986     if( !sign_mode ) {/* see whether we have a matching secret key */
987         PKT_public_key *pk = keyblock->pkt->pkt.public_key;
988
989         sec_kdbhd = keydb_new (1);
990         {
991             byte afp[MAX_FINGERPRINT_LEN];
992             size_t an;
993
994             fingerprint_from_pk (pk, afp, &an);
995             while (an < MAX_FINGERPRINT_LEN) 
996                 afp[an++] = 0;
997             rc = keydb_search_fpr (sec_kdbhd, afp);
998         }
999         if (!rc) {
1000             rc = keydb_get_keyblock (sec_kdbhd, &sec_keyblock);
1001             if (rc) {
1002                 log_error (_("error reading secret keyblock `%s': %s\n"),
1003                                                 username, g10_errstr(rc));
1004             }
1005             else {
1006                 merge_keys_and_selfsig( sec_keyblock );
1007                 if( fix_keyblock( sec_keyblock ) )
1008                     sec_modified++;
1009             }
1010         }
1011
1012         if (rc) {
1013             sec_keyblock = NULL;
1014             keydb_release (sec_kdbhd); sec_kdbhd = NULL;
1015             rc = 0;
1016         }
1017     }
1018
1019     if( sec_keyblock ) { 
1020         tty_printf(_("Secret key is available.\n"));
1021     }
1022
1023     toggle = 0;
1024     cur_keyblock = keyblock;
1025     for(;;) { /* main loop */
1026         int i, arg_number, photo;
1027         const char *arg_string = "";
1028         char *p;
1029         PKT_public_key *pk=keyblock->pkt->pkt.public_key;
1030
1031         tty_printf("\n");
1032         if( redisplay ) {
1033             show_key_with_all_names( cur_keyblock, 0, 1, 0, 1, 0 );
1034             tty_printf("\n");
1035             redisplay = 0;
1036         }
1037         do {
1038             m_free(answer);
1039             if( have_commands ) {
1040                 if( commands ) {
1041                     answer = m_strdup( commands->d );
1042                     commands = commands->next;
1043                 }
1044                 else if( opt.batch ) {
1045                     answer = m_strdup("quit");
1046                 }
1047                 else
1048                     have_commands = 0;
1049             }
1050             if( !have_commands ) {
1051                 answer = cpr_get_no_help("keyedit.prompt", _("Command> "));
1052                 cpr_kill_prompt();
1053             }
1054             trim_spaces(answer);
1055         } while( *answer == '#' );
1056
1057         arg_number = 0; /* Yes, here is the init which egcc complains about */
1058         photo = 0; /* This too */
1059         if( !*answer )
1060             cmd = cmdLIST;
1061         else if( *answer == CONTROL_D )
1062             cmd = cmdQUIT;
1063         else if( isdigit( *answer ) ) {
1064             cmd = cmdSELUID;
1065             arg_number = atoi(answer);
1066         }
1067         else {
1068             if( (p=strchr(answer,' ')) ) {
1069                 *p++ = 0;
1070                 trim_spaces(answer);
1071                 trim_spaces(p);
1072                 arg_number = atoi(p);
1073                 arg_string = p;
1074             }
1075
1076             for(i=0; cmds[i].name; i++ ) {
1077                 if( !ascii_strcasecmp( answer, cmds[i].name ) )
1078                     break;
1079             }
1080             if( sign_mode && !cmds[i].signmode )
1081                 cmd = cmdINVCMD;
1082             else if( cmds[i].need_sk && !sec_keyblock ) {
1083                 tty_printf(_("Need the secret key to do this.\n"));
1084                 cmd = cmdNOP;
1085             }
1086             else if( cmds[i].not_with_sk && sec_keyblock && toggle ) {
1087                 tty_printf(_("Please use the command \"toggle\" first.\n"));
1088                 cmd = cmdNOP;
1089             }
1090             else
1091                 cmd = cmds[i].id;
1092         }
1093         switch( cmd )  {
1094           case cmdHELP:
1095             for(i=0; cmds[i].name; i++ ) {
1096                 if( sign_mode && !cmds[i].signmode )
1097                     ;
1098                 else if( cmds[i].need_sk && !sec_keyblock )
1099                     ; /* skip if we do not have the secret key */
1100                 else if( cmds[i].desc )
1101                     tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
1102             }
1103             break;
1104
1105           case cmdLIST:
1106             redisplay = 1;
1107             break;
1108
1109           case cmdFPR:
1110             show_key_and_fingerprint( keyblock );
1111             break;
1112
1113           case cmdSELUID:
1114             if( menu_select_uid( cur_keyblock, arg_number ) )
1115                 redisplay = 1;
1116             break;
1117
1118           case cmdSELKEY:
1119             if( menu_select_key( cur_keyblock, arg_number ) )
1120                 redisplay = 1;
1121             break;
1122
1123           case cmdCHECK:
1124             /* we can only do this with the public key becuase the
1125              * check functions can't cope with secret keys and it
1126              * is questionable whether this would make sense at all */
1127             check_all_keysigs( keyblock, count_selected_uids(keyblock) );
1128             break;
1129
1130           case cmdSIGN: /* sign (only the public key) */
1131           case cmdLSIGN: /* sign (only the public key) */
1132           case cmdNRSIGN: /* sign (only the public key) */
1133           case cmdNRLSIGN: /* sign (only the public key) */
1134             if( pk->is_revoked )
1135               {
1136                 tty_printf(_("Key is revoked."));
1137
1138                 if(opt.expert)
1139                   {
1140                     tty_printf("  ");
1141                     if(!cpr_get_answer_is_yes("keyedit.sign_revoked.okay",
1142                                               _("Are you sure you still want "
1143                                                 "to sign it? (y/N) ")))
1144                       break;
1145                   }
1146                 else
1147                   {
1148                     tty_printf(_("  Unable to sign.\n"));
1149                     break;
1150                   }
1151               }
1152
1153             if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
1154                 if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
1155                                            _("Really sign all user IDs? ")) ) {
1156                     tty_printf(_("Hint: Select the user IDs to sign\n"));
1157                     break;
1158                 }
1159             }
1160             if( !sign_uids( keyblock, locusr, &modified,
1161                             (cmd == cmdLSIGN) || (cmd == cmdNRLSIGN),
1162                             (cmd == cmdNRSIGN) || (cmd==cmdNRLSIGN))
1163                 && sign_mode )
1164                 goto do_cmd_save;
1165             break;
1166
1167           case cmdDEBUG:
1168             dump_kbnode( cur_keyblock );
1169             break;
1170
1171           case cmdTOGGLE:
1172             toggle = !toggle;
1173             cur_keyblock = toggle? sec_keyblock : keyblock;
1174             redisplay = 1;
1175             break;
1176
1177           case cmdADDPHOTO:
1178             if (opt.rfc2440 || opt.rfc1991 || opt.pgp2)
1179               {
1180                 tty_printf(
1181                    _("This command is not allowed while in %s mode.\n"),
1182                    opt.rfc2440?"OpenPGP":opt.pgp2?"PGP2":"RFC-1991");
1183                 break;
1184               }
1185             photo=1;
1186             /* fall through */
1187
1188           case cmdADDUID:
1189             if( menu_adduid( keyblock, sec_keyblock, photo ) ) {
1190                 redisplay = 1;
1191                 sec_modified = modified = 1;
1192                 merge_keys_and_selfsig( sec_keyblock );
1193                 merge_keys_and_selfsig( keyblock );
1194             }
1195             break;
1196
1197           case cmdDELUID: {
1198                 int n1;
1199
1200                 if( !(n1=count_selected_uids(keyblock)) )
1201                     tty_printf(_("You must select at least one user ID.\n"));
1202                 else if( real_uids_left(keyblock) < 1 )
1203                     tty_printf(_("You can't delete the last user ID!\n"));
1204                 else if( cpr_get_answer_is_yes(
1205                             "keyedit.remove.uid.okay",
1206                         n1 > 1? _("Really remove all selected user IDs? ")
1207                               : _("Really remove this user ID? ")
1208                        ) ) {
1209                     menu_deluid( keyblock, sec_keyblock );
1210                     redisplay = 1;
1211                     modified = 1;
1212                     if( sec_keyblock )
1213                        sec_modified = 1;
1214                 }
1215             }
1216             break;
1217
1218           case cmdDELSIG: {
1219                 int n1;
1220
1221                 if( !(n1=count_selected_uids(keyblock)) )
1222                     tty_printf(_("You must select at least one user ID.\n"));
1223                 else if( menu_delsig( keyblock ) ) {
1224                     /* no redisplay here, because it may scroll away some
1225                      * status output of delsig */
1226                     modified = 1;
1227                 }
1228             }
1229             break;
1230
1231           case cmdADDKEY:
1232             if( generate_subkeypair( keyblock, sec_keyblock ) ) {
1233                 redisplay = 1;
1234                 sec_modified = modified = 1;
1235                 merge_keys_and_selfsig( sec_keyblock );
1236                 merge_keys_and_selfsig( keyblock );
1237             }
1238             break;
1239
1240
1241           case cmdDELKEY: {
1242                 int n1;
1243
1244                 if( !(n1=count_selected_keys( keyblock )) )
1245                     tty_printf(_("You must select at least one key.\n"));
1246                 else if( sec_keyblock && !cpr_get_answer_is_yes(
1247                             "keyedit.remove.subkey.okay",
1248                        n1 > 1?
1249                         _("Do you really want to delete the selected keys? "):
1250                         _("Do you really want to delete this key? ")
1251                        ))
1252                     ;
1253                 else {
1254                     menu_delkey( keyblock, sec_keyblock );
1255                     redisplay = 1;
1256                     modified = 1;
1257                     if( sec_keyblock )
1258                        sec_modified = 1;
1259                 }
1260             }
1261             break;
1262
1263           case cmdADDREVOKER:
1264             {
1265               int sensitive=0;
1266
1267               if(arg_string && ascii_strcasecmp(arg_string,"sensitive")==0)
1268                 sensitive=1;
1269               if( menu_addrevoker( keyblock, sec_keyblock, sensitive ) ) {
1270                 redisplay = 1;
1271                 sec_modified = modified = 1;
1272                 merge_keys_and_selfsig( sec_keyblock );
1273                 merge_keys_and_selfsig( keyblock );
1274               }
1275             }
1276             break;
1277
1278           case cmdREVKEY: {
1279                 int n1;
1280
1281                 if( !(n1=count_selected_keys( keyblock )) )
1282                     tty_printf(_("You must select at least one key.\n"));
1283                 else if( sec_keyblock && !cpr_get_answer_is_yes(
1284                             "keyedit.revoke.subkey.okay",
1285                        n1 > 1?
1286                         _("Do you really want to revoke the selected keys? "):
1287                         _("Do you really want to revoke this key? ")
1288                        ))
1289                     ;
1290                 else {
1291                     if( menu_revkey( keyblock, sec_keyblock ) ) {
1292                         modified = 1;
1293                         /*sec_modified = 1;*/
1294                     }
1295                     redisplay = 1;
1296                 }
1297             }
1298             break;
1299
1300           case cmdEXPIRE:
1301             if( menu_expire( keyblock, sec_keyblock ) ) {
1302                 merge_keys_and_selfsig( sec_keyblock );
1303                 merge_keys_and_selfsig( keyblock );
1304                 sec_modified = 1;
1305                 modified = 1;
1306                 redisplay = 1;
1307             }
1308             break;
1309
1310           case cmdPRIMARY:
1311             if( menu_set_primary_uid ( keyblock, sec_keyblock ) ) {
1312                 merge_keys_and_selfsig( keyblock );
1313                 modified = 1;
1314                 redisplay = 1;
1315             }
1316             break;
1317
1318           case cmdPASSWD:
1319             if( change_passphrase( sec_keyblock ) )
1320                 sec_modified = 1;
1321             break;
1322
1323           case cmdTRUST:
1324             show_key_with_all_names( keyblock, 0, 0, 0, 1, 0 );
1325             tty_printf("\n");
1326             if( edit_ownertrust( find_kbnode( keyblock,
1327                                  PKT_PUBLIC_KEY )->pkt->pkt.public_key, 1 ) ) {
1328                 redisplay = 1;
1329                 /* No real need to set update_trust here as
1330                    edit_ownertrust() calls revalidation_mark()
1331                    anyway. */
1332                 update_trust=1;
1333             }
1334             break;
1335
1336           case cmdPREF:
1337             show_key_with_all_names( keyblock, 0, 0, 0, 0, 1 );
1338             break;
1339
1340           case cmdSHOWPREF:
1341             show_key_with_all_names( keyblock, 0, 0, 0, 0, 2 );
1342             break;
1343
1344           case cmdSETPREF:
1345             keygen_set_std_prefs ( !*arg_string? "default" : arg_string, 0);
1346             break;
1347
1348           case cmdUPDPREF: 
1349             {
1350               PKT_user_id *temp=keygen_get_std_prefs();
1351               tty_printf(_("Current preference list:\n"));
1352               show_prefs(temp,1);
1353               m_free(temp);
1354             }
1355             if (cpr_get_answer_is_yes ("keyedit.updpref.okay",
1356                                         count_selected_uids (keyblock)?
1357                                         _("Really update the preferences"
1358                                           " for the selected user IDs? "):
1359                                        _("Really update the preferences? "))){
1360
1361                 if ( menu_set_preferences (keyblock, sec_keyblock) ) {
1362                     merge_keys_and_selfsig (keyblock);
1363                     modified = 1;
1364                     redisplay = 1;
1365                 }
1366             }
1367             break;
1368
1369           case cmdNOP:
1370             break;
1371
1372           case cmdREVSIG:
1373             if( menu_revsig( keyblock ) ) {
1374                 redisplay = 1;
1375                 modified = 1;
1376             }
1377             break;
1378
1379           case cmdENABLEKEY:
1380           case cmdDISABLEKEY:
1381             if( enable_disable_key( keyblock, cmd == cmdDISABLEKEY ) ) {
1382                 redisplay = 1;
1383                 modified = 1;
1384             }
1385             break;
1386
1387          case cmdSHOWPHOTO:
1388            menu_showphoto(keyblock);
1389            break;
1390
1391           case cmdQUIT:
1392             if( have_commands )
1393                 goto leave;
1394             if( !modified && !sec_modified )
1395                 goto leave;
1396             if( !cpr_get_answer_is_yes("keyedit.save.okay",
1397                                         _("Save changes? ")) ) {
1398                 if( cpr_enabled()
1399                     || cpr_get_answer_is_yes("keyedit.cancel.okay",
1400                                              _("Quit without saving? ")) )
1401                     goto leave;
1402                 break;
1403             }
1404             /* fall thru */
1405           case cmdSAVE:
1406           do_cmd_save:
1407             if( modified || sec_modified  ) {
1408                 if( modified ) {
1409                     rc = keydb_update_keyblock (kdbhd, keyblock);
1410                     if( rc ) {
1411                         log_error(_("update failed: %s\n"), g10_errstr(rc) );
1412                         break;
1413                     }
1414                 }
1415                 if( sec_modified ) {
1416                     rc = keydb_update_keyblock (sec_kdbhd, sec_keyblock );
1417                     if( rc ) {
1418                         log_error( _("update secret failed: %s\n"),
1419                                    g10_errstr(rc) );
1420                         break;
1421                     }
1422                 }
1423             }
1424             else
1425                 tty_printf(_("Key not changed so no update needed.\n"));
1426
1427             if( update_trust )
1428               {
1429                 revalidation_mark ();
1430                 update_trust=0;
1431               }
1432             goto leave;
1433
1434           case cmdINVCMD:
1435           default:
1436             tty_printf("\n");
1437             tty_printf(_("Invalid command  (try \"help\")\n"));
1438             break;
1439         }
1440     } /* end main loop */
1441
1442   leave:
1443     release_kbnode( keyblock );
1444     release_kbnode( sec_keyblock );
1445     keydb_release (kdbhd);
1446     m_free(answer);
1447 }
1448
1449
1450 /****************
1451  * show preferences of a public keyblock.
1452  */
1453 static void
1454 show_prefs (PKT_user_id *uid, int verbose)
1455 {
1456     const prefitem_t fake={0,0};
1457     const prefitem_t *prefs;
1458     int i;
1459
1460     if( !uid )
1461         return;
1462
1463     if( uid->prefs )
1464         prefs=uid->prefs;
1465     else if(verbose)
1466         prefs=&fake;
1467     else
1468       return;
1469
1470     if (verbose) {
1471         int any, des_seen=0, sha1_seen=0, uncomp_seen=0;
1472         tty_printf ("     Cipher: ");
1473         for(i=any=0; prefs[i].type; i++ ) {
1474             if( prefs[i].type == PREFTYPE_SYM ) {
1475                 const char *s = cipher_algo_to_string (prefs[i].value);
1476                 
1477                 if (any)
1478                     tty_printf (", ");
1479                 any = 1;
1480                 /* We don't want to display strings for experimental algos */
1481                 if (s && prefs[i].value < 100 )
1482                     tty_printf ("%s", s );
1483                 else
1484                     tty_printf ("[%d]", prefs[i].value);
1485                 if (prefs[i].value == CIPHER_ALGO_3DES )
1486                     des_seen = 1;
1487             }    
1488         }
1489         if (!des_seen) {
1490             if (any)
1491                 tty_printf (", ");
1492             tty_printf ("%s",cipher_algo_to_string(CIPHER_ALGO_3DES));
1493         }
1494         tty_printf ("\n     Hash: ");
1495         for(i=any=0; prefs[i].type; i++ ) {
1496             if( prefs[i].type == PREFTYPE_HASH ) {
1497                 const char *s = digest_algo_to_string (prefs[i].value);
1498                 
1499                 if (any)
1500                     tty_printf (", ");
1501                 any = 1;
1502                 /* We don't want to display strings for experimental algos */
1503                 if (s && prefs[i].value < 100 )
1504                     tty_printf ("%s", s );
1505                 else
1506                     tty_printf ("[%d]", prefs[i].value);
1507                 if (prefs[i].value == DIGEST_ALGO_SHA1 )
1508                     sha1_seen = 1;
1509             }
1510         }
1511         if (!sha1_seen) {
1512             if (any)
1513                 tty_printf (", ");
1514             tty_printf ("%s",digest_algo_to_string(DIGEST_ALGO_SHA1));
1515         }
1516         tty_printf ("\n     Compression: ");
1517         for(i=any=0; prefs[i].type; i++ ) {
1518             if( prefs[i].type == PREFTYPE_ZIP ) {
1519                 const char *s=compress_algo_to_string(prefs[i].value);
1520                 
1521                 if (any)
1522                     tty_printf (", ");
1523                 any = 1;
1524                 /* We don't want to display strings for experimental algos */
1525                 if (s && prefs[i].value < 100 )
1526                     tty_printf ("%s", s );
1527                 else
1528                     tty_printf ("[%d]", prefs[i].value);
1529                 if (prefs[i].value == 0 )
1530                     uncomp_seen = 1;
1531             }
1532         }
1533         if (!uncomp_seen) {
1534             if (any)
1535                 tty_printf (", ");
1536             else {
1537               tty_printf ("%s",compress_algo_to_string(1));
1538               tty_printf (", ");
1539             }
1540             tty_printf ("%s",compress_algo_to_string(0));
1541         }
1542         tty_printf ("\n     Features: ");
1543         if(uid->mdc_feature)
1544           tty_printf ("MDC");
1545         tty_printf("\n");
1546     }
1547     else {
1548         tty_printf("    ");
1549         for(i=0; prefs[i].type; i++ ) {
1550             tty_printf( " %c%d", prefs[i].type == PREFTYPE_SYM   ? 'S' :
1551                                  prefs[i].type == PREFTYPE_HASH  ? 'H' :
1552                                  prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
1553                                  prefs[i].value);
1554         }
1555         if (uid->mdc_feature)
1556             tty_printf (" [mdc]");
1557         tty_printf("\n");
1558     }
1559 }
1560
1561
1562 /* This is the version of show_key_with_all_names used when
1563    opt.with_colons is used.  It prints all available data in a easy to
1564    parse format and does not translate utf8 */
1565 static void
1566 show_key_with_all_names_colon (KBNODE keyblock)
1567 {
1568   KBNODE node;
1569   int i, j;
1570   byte pk_version=0;
1571
1572   /* the keys */
1573   for ( node = keyblock; node; node = node->next )
1574     {
1575       if (node->pkt->pkttype == PKT_PUBLIC_KEY
1576           || (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) )
1577         {
1578           PKT_public_key *pk = node->pkt->pkt.public_key;
1579           int otrust=0, trust=0;
1580           u32 keyid[2];
1581
1582           if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1583             {
1584               trust = get_validity_info (pk, NULL);
1585               otrust = get_ownertrust_info (pk);
1586               pk_version = pk->version;
1587             }
1588
1589           keyid_from_pk (pk, keyid);
1590
1591           fputs (node->pkt->pkttype == PKT_PUBLIC_KEY?"pub:":"sub:", stdout);
1592           if (!pk->is_valid)
1593             putchar ('i');
1594           else if (pk->is_revoked)
1595             putchar ('r');
1596           else if (pk->has_expired)
1597             putchar ('e');
1598           else 
1599             putchar (trust);
1600           printf (":%u:%d:%08lX%08lX:%lu:%lu:",
1601                   nbits_from_pk (pk),
1602                   pk->pubkey_algo,
1603                   (ulong)keyid[0], (ulong)keyid[1],
1604                   (ulong)pk->timestamp,
1605                   (ulong)pk->expiredate );
1606           if (pk->local_id)
1607             printf ("%lu", pk->local_id);
1608           putchar (':');
1609           putchar (otrust);
1610           putchar(':');
1611           putchar('\n');
1612           
1613           print_fingerprint (pk, NULL, 0);
1614
1615           /* print the revoker record */
1616           if( !pk->revkey && pk->numrevkeys )
1617             BUG();
1618           else
1619             {
1620               for (i=0; i < pk->numrevkeys; i++)
1621                 {
1622                   byte *p;
1623
1624                   printf ("rvk:::%d::::::", pk->revkey[i].algid);
1625                   p = pk->revkey[i].fpr;
1626                   for (j=0; j < 20; j++, p++ )
1627                     printf ("%02X", *p);
1628                   printf (":%02x%s:\n", pk->revkey[i].class,
1629                           (pk->revkey[i].class&0x40)?"s":"");
1630                 }
1631             }
1632         }
1633     }
1634   
1635     /* the user ids */
1636     i = 0;
1637     for (node = keyblock; node; node = node->next) 
1638       {
1639         if ( node->pkt->pkttype == PKT_USER_ID )
1640           {
1641             PKT_user_id *uid = node->pkt->pkt.user_id;
1642             int trustletter = '?';
1643
1644             ++i;
1645             if(uid->attrib_data)
1646               {
1647                 printf ("uat:%c::::::::%u %lu", trustletter,
1648                         uid->numattribs,uid->attrib_len);
1649               }
1650             else
1651               {
1652                 printf ("uid:%c::::::::", trustletter);
1653                 print_string (stdout, uid->name, uid->len, ':');
1654               }
1655             putchar (':');
1656             /* signature class */
1657             putchar (':');
1658             /* capabilities */
1659             putchar (':');
1660             /* preferences */
1661             if (pk_version>3 || uid->selfsigversion>3)
1662               {
1663                 const prefitem_t *prefs = uid->prefs;
1664                 
1665                 for (j=0; prefs && prefs[j].type; j++)
1666                   {
1667                     if (j)
1668                       putchar (' ');
1669                     printf ("%c%d", prefs[j].type == PREFTYPE_SYM   ? 'S' :
1670                             prefs[j].type == PREFTYPE_HASH  ? 'H' :
1671                             prefs[j].type == PREFTYPE_ZIP ? 'Z':'?',
1672                             prefs[j].value);
1673                   } 
1674                 if (uid->mdc_feature)
1675                   printf (",mdc");
1676               } 
1677             putchar (':');
1678             /* flags */
1679             printf ("%d,", i);
1680             if (uid->is_primary)
1681               putchar ('p');
1682             if (uid->is_revoked)
1683               putchar ('r');
1684             if (uid->is_expired)
1685               putchar ('e');
1686             if ((node->flag & NODFLG_SELUID))
1687               putchar ('s');
1688             if ((node->flag & NODFLG_MARK_A))
1689               putchar ('m');
1690             putchar (':');
1691             putchar('\n');
1692           }
1693       }
1694 }
1695
1696
1697 /****************
1698  * Display the key a the user ids, if only_marked is true, do only
1699  * so for user ids with mark A flag set and dont display the index number
1700  */
1701 static void
1702 show_key_with_all_names( KBNODE keyblock, int only_marked, int with_revoker,
1703                          int with_fpr, int with_subkeys, int with_prefs )
1704 {
1705     KBNODE node;
1706     int i, rc;
1707     int do_warn = 0;
1708     byte pk_version=0;
1709
1710     if (opt.with_colons)
1711       {
1712         show_key_with_all_names_colon (keyblock);
1713         return;
1714       }
1715
1716     /* the keys */
1717     for( node = keyblock; node; node = node->next ) {
1718         if( node->pkt->pkttype == PKT_PUBLIC_KEY
1719             || (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
1720             PKT_public_key *pk = node->pkt->pkt.public_key;
1721             int otrust=0, trust=0;
1722
1723             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1724                 /* do it here, so that debug messages don't clutter the
1725                  * output */
1726                 static int did_warn = 0;
1727
1728                 trust = get_validity_info (pk, NULL);
1729                 otrust = get_ownertrust_info (pk);
1730
1731                 /* Show a warning once */
1732                 if (!did_warn
1733                     && (get_validity (pk, NULL) & TRUST_FLAG_PENDING_CHECK)) {
1734                     did_warn = 1;
1735                     do_warn = 1;
1736                 }
1737
1738                 pk_version=pk->version;
1739             }
1740
1741             if(with_revoker) {
1742                 if( !pk->revkey && pk->numrevkeys )
1743                     BUG();
1744                 else
1745                     for(i=0;i<pk->numrevkeys;i++) {
1746                         u32 r_keyid[2];
1747                         char *user;
1748            
1749                         keyid_from_fingerprint(pk->revkey[i].fpr,
1750                                                MAX_FINGERPRINT_LEN,r_keyid);
1751                         
1752                         user=get_user_id_string (r_keyid);
1753                         tty_printf (_("This key may be revoked by %s key "),
1754                                  pubkey_algo_to_string (pk->revkey[i].algid));
1755                         tty_print_utf8_string (user, strlen (user));
1756                         if ((pk->revkey[i].class&0x40))
1757                           tty_printf (_(" (sensitive)"));
1758                         tty_printf ("\n");
1759                         m_free(user);
1760                       }
1761             }
1762
1763             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1764                           node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
1765                           (node->flag & NODFLG_SELKEY)? '*':' ',
1766                           nbits_from_pk( pk ),
1767                           pubkey_letter( pk->pubkey_algo ),
1768                           (ulong)keyid_from_pk(pk,NULL),
1769                           datestr_from_pk(pk),
1770                           expirestr_from_pk(pk) );
1771             if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1772                 tty_printf(_(" trust: %c/%c"), otrust, trust );
1773                 if( node->pkt->pkttype == PKT_PUBLIC_KEY
1774                     && (get_ownertrust (pk)&TRUST_FLAG_DISABLED)) {
1775                     tty_printf("\n*** ");
1776                     tty_printf(_("This key has been disabled"));
1777                 }
1778
1779                 if( with_fpr  ) {
1780                     tty_printf("\n");
1781                     print_fingerprint ( pk, NULL, 2 );
1782                 }
1783             }
1784             tty_printf("\n");
1785         }
1786         else if( node->pkt->pkttype == PKT_SECRET_KEY
1787             || (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
1788             PKT_secret_key *sk = node->pkt->pkt.secret_key;
1789             tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1790                           node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
1791                           (node->flag & NODFLG_SELKEY)? '*':' ',
1792                           nbits_from_sk( sk ),
1793                           pubkey_letter( sk->pubkey_algo ),
1794                           (ulong)keyid_from_sk(sk,NULL),
1795                           datestr_from_sk(sk),
1796                           expirestr_from_sk(sk) );
1797             tty_printf("\n");
1798         }
1799         else if( with_subkeys && node->pkt->pkttype == PKT_SIGNATURE
1800                  && node->pkt->pkt.signature->sig_class == 0x28       ) {
1801             PKT_signature *sig = node->pkt->pkt.signature;
1802
1803             rc = check_key_signature( keyblock, node, NULL );
1804             if( !rc )
1805                 tty_printf( _("rev! subkey has been revoked: %s\n"),
1806                             datestr_from_sig( sig ) );
1807             else if( rc == G10ERR_BAD_SIGN )
1808                 tty_printf( _("rev- faked revocation found\n") );
1809             else if( rc )
1810                 tty_printf( _("rev? problem checking revocation: %s\n"),
1811                                                          g10_errstr(rc) );
1812         }
1813     }
1814     /* the user ids */
1815     i = 0;
1816     for( node = keyblock; node; node = node->next ) {
1817         if( node->pkt->pkttype == PKT_USER_ID ) {
1818             PKT_user_id *uid = node->pkt->pkt.user_id;
1819             ++i;
1820             if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
1821                 if( only_marked )
1822                    tty_printf("     ");
1823                 else if( node->flag & NODFLG_SELUID )
1824                    tty_printf("(%d)* ", i);
1825                 else if( uid->is_primary )
1826                    tty_printf("(%d). ", i);
1827                 else
1828                    tty_printf("(%d)  ", i);
1829                 if ( uid->is_revoked )
1830                     tty_printf ("[revoked] ");
1831                 if ( uid->is_expired )
1832                     tty_printf ("[expired] ");
1833                 tty_print_utf8_string( uid->name, uid->len );
1834                 tty_printf("\n");
1835                 if( with_prefs )
1836                   {
1837                     if(pk_version>3 || uid->selfsigversion>3)
1838                       show_prefs (uid, with_prefs == 2);
1839                     else
1840                       tty_printf(_("There are no preferences on a "
1841                                    "PGP 2.x-style user ID.\n"));
1842                   }
1843             }
1844         }
1845     }
1846
1847     if (do_warn)
1848         tty_printf (_("Please note that the shown key validity "
1849                       "is not necessarily correct\n"
1850                       "unless you restart the program.\n")); 
1851
1852 }
1853
1854
1855 /* Display basic key information.  This fucntion is suitable to show
1856    information on the key without any dependencies on the trustdb or
1857    any other internal GnuPG stuff.  KEYBLOCK may either be a public or
1858    a secret key.*/
1859 void
1860 show_basic_key_info ( KBNODE keyblock )
1861 {
1862   KBNODE node;
1863   int i;
1864
1865   /* The primary key */
1866   for (node = keyblock; node; node = node->next)
1867     {
1868       if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1869         {
1870           PKT_public_key *pk = node->pkt->pkt.public_key;
1871           
1872           /* Note, we use the same format string as in other show
1873              functions to make the translation job easier. */
1874           tty_printf (_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1875                       node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
1876                       ' ',
1877                       nbits_from_pk( pk ),
1878                       pubkey_letter( pk->pubkey_algo ),
1879                       (ulong)keyid_from_pk(pk,NULL),
1880                       datestr_from_pk(pk),
1881                       expirestr_from_pk(pk) );
1882           tty_printf("\n");
1883           print_fingerprint ( pk, NULL, 3 );
1884           tty_printf("\n");
1885         }
1886       else if (node->pkt->pkttype == PKT_SECRET_KEY)
1887         {
1888           PKT_secret_key *sk = node->pkt->pkt.secret_key;
1889           tty_printf(_("%s%c %4u%c/%08lX  created: %s expires: %s"),
1890                      node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb",
1891                      ' ',
1892                      nbits_from_sk( sk ),
1893                      pubkey_letter( sk->pubkey_algo ),
1894                      (ulong)keyid_from_sk(sk,NULL),
1895                      datestr_from_sk(sk),
1896                      expirestr_from_sk(sk) );
1897           tty_printf("\n");
1898           print_fingerprint (NULL, sk, 3 );
1899           tty_printf("\n");
1900         }
1901     }
1902
1903   /* The user IDs. */
1904   for (i=0, node = keyblock; node; node = node->next)
1905     {
1906       if (node->pkt->pkttype == PKT_USER_ID)
1907         {
1908           PKT_user_id *uid = node->pkt->pkt.user_id;
1909           ++i;
1910      
1911           tty_printf ("     ");
1912           if (uid->is_revoked)
1913             tty_printf ("[revoked] ");
1914           if ( uid->is_expired )
1915             tty_printf ("[expired] ");
1916           tty_print_utf8_string (uid->name, uid->len);
1917           tty_printf ("\n");
1918         }
1919     }
1920 }
1921
1922 static void
1923 show_key_and_fingerprint( KBNODE keyblock )
1924 {
1925     KBNODE node;
1926     PKT_public_key *pk = NULL;
1927
1928     for( node = keyblock; node; node = node->next ) {
1929         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
1930             pk = node->pkt->pkt.public_key;
1931             tty_printf("pub   %4u%c/%08lX %s ",
1932                           nbits_from_pk( pk ),
1933                           pubkey_letter( pk->pubkey_algo ),
1934                           (ulong)keyid_from_pk(pk,NULL),
1935                           datestr_from_pk(pk) );
1936         }
1937         else if( node->pkt->pkttype == PKT_USER_ID ) {
1938             PKT_user_id *uid = node->pkt->pkt.user_id;
1939             tty_print_utf8_string( uid->name, uid->len );
1940             break;
1941         }
1942     }
1943     tty_printf("\n");
1944     if( pk )
1945         print_fingerprint( pk, NULL, 2 );
1946 }
1947
1948
1949
1950 /****************
1951  * Ask for a new user id, do the selfsignature and put it into
1952  * both keyblocks.
1953  * Return true if there is a new user id
1954  */
1955 static int
1956 menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock, int photo)
1957 {
1958     PKT_user_id *uid;
1959     PKT_public_key *pk=NULL;
1960     PKT_secret_key *sk=NULL;
1961     PKT_signature *sig=NULL;
1962     PACKET *pkt;
1963     KBNODE node;
1964     KBNODE pub_where=NULL, sec_where=NULL;
1965     int rc;
1966
1967     for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
1968         if( node->pkt->pkttype == PKT_PUBLIC_KEY )
1969             pk = node->pkt->pkt.public_key;
1970         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
1971             break;
1972     }
1973     if( !node ) /* no subkey */
1974         pub_where = NULL;
1975     for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
1976         if( node->pkt->pkttype == PKT_SECRET_KEY )
1977             sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
1978         else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
1979             break;
1980     }
1981     if( !node ) /* no subkey */
1982         sec_where = NULL;
1983     assert(pk && sk);
1984
1985     if(photo) {
1986       int hasattrib=0;
1987
1988       for( node = pub_keyblock; node; node = node->next )
1989         if( node->pkt->pkttype == PKT_USER_ID &&
1990             node->pkt->pkt.user_id->attrib_data!=NULL)
1991           {
1992             hasattrib=1;
1993             break;
1994           }
1995
1996       /* It is legal but bad for compatibility to add a photo ID to a
1997          v3 key as it means that PGP2 will not be able to use that key
1998          anymore.  Also, PGP may not expect a photo on a v3 key.
1999          Don't bother to ask this if the key already has a photo - any
2000          damage has already been done at that point. -dms */
2001       if(pk->version==3 && !hasattrib)
2002         {
2003           if(opt.expert)
2004             {
2005               tty_printf(_("WARNING: This is a PGP2-style key.  "
2006                            "Adding a photo ID may cause some versions\n"
2007                            "         of PGP to reject this key.\n"));
2008
2009               if(!cpr_get_answer_is_yes("keyedit.v3_photo.okay",
2010                                         _("Are you sure you still want "
2011                                           "to add it? (y/N) ")))
2012                 return 0;
2013             }
2014           else
2015             {
2016               tty_printf(_("You may not add a photo ID to "
2017                            "a PGP2-style key.\n"));
2018               return 0;
2019             }
2020         }
2021
2022       uid = generate_photo_id(pk);
2023     } else
2024       uid = generate_user_id();
2025     if( !uid )
2026         return 0;
2027
2028     rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0, 0, 0, 0,
2029                              keygen_add_std_prefs, pk );
2030     free_secret_key( sk );
2031     if( rc ) {
2032         log_error("signing failed: %s\n", g10_errstr(rc) );
2033         free_user_id(uid);
2034         return 0;
2035     }
2036
2037     /* insert/append to secret keyblock */
2038     pkt = m_alloc_clear( sizeof *pkt );
2039     pkt->pkttype = PKT_USER_ID;
2040     pkt->pkt.user_id = scopy_user_id(uid);
2041     node = new_kbnode(pkt);
2042     if( sec_where )
2043         insert_kbnode( sec_where, node, 0 );
2044     else
2045         add_kbnode( sec_keyblock, node );
2046     pkt = m_alloc_clear( sizeof *pkt );
2047     pkt->pkttype = PKT_SIGNATURE;
2048     pkt->pkt.signature = copy_signature(NULL, sig);
2049     if( sec_where )
2050         insert_kbnode( node, new_kbnode(pkt), 0 );
2051     else
2052         add_kbnode( sec_keyblock, new_kbnode(pkt) );
2053     /* insert/append to public keyblock */
2054     pkt = m_alloc_clear( sizeof *pkt );
2055     pkt->pkttype = PKT_USER_ID;
2056     pkt->pkt.user_id = uid;
2057     node = new_kbnode(pkt);
2058     if( pub_where )
2059         insert_kbnode( pub_where, node, 0 );
2060     else
2061         add_kbnode( pub_keyblock, node );
2062     pkt = m_alloc_clear( sizeof *pkt );
2063     pkt->pkttype = PKT_SIGNATURE;
2064     pkt->pkt.signature = copy_signature(NULL, sig);
2065     if( pub_where )
2066         insert_kbnode( node, new_kbnode(pkt), 0 );
2067     else
2068         add_kbnode( pub_keyblock, new_kbnode(pkt) );
2069     return 1;
2070 }
2071
2072
2073 /****************
2074  * Remove all selceted userids from the keyrings
2075  */
2076 static void
2077 menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
2078 {
2079     KBNODE node;
2080     int selected=0;
2081
2082     for( node = pub_keyblock; node; node = node->next ) {
2083         if( node->pkt->pkttype == PKT_USER_ID ) {
2084             selected = node->flag & NODFLG_SELUID;
2085             if( selected ) {
2086                 /* Only cause a trust update if we delete a
2087                    non-revoked user id */
2088                 if(!node->pkt->pkt.user_id->is_revoked)
2089                   update_trust=1;
2090                 delete_kbnode( node );
2091                 if( sec_keyblock ) {
2092                     KBNODE snode;
2093                     int s_selected = 0;
2094                     PKT_user_id *uid = node->pkt->pkt.user_id;
2095                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2096                         if( snode->pkt->pkttype == PKT_USER_ID ) {
2097                             PKT_user_id *suid = snode->pkt->pkt.user_id;
2098
2099                             s_selected =
2100                                 (uid->len == suid->len
2101                                  && !memcmp( uid->name, suid->name, uid->len));
2102                             if( s_selected )
2103                                 delete_kbnode( snode );
2104                         }
2105                         else if( s_selected
2106                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2107                             delete_kbnode( snode );
2108                         else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
2109                             s_selected = 0;
2110                     }
2111                 }
2112             }
2113         }
2114         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2115             delete_kbnode( node );
2116         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2117             selected = 0;
2118     }
2119     commit_kbnode( &pub_keyblock );
2120     if( sec_keyblock )
2121         commit_kbnode( &sec_keyblock );
2122 }
2123
2124
2125 static int
2126 menu_delsig( KBNODE pub_keyblock )
2127 {
2128     KBNODE node;
2129     PKT_user_id *uid = NULL;
2130     int changed=0;
2131
2132     for( node = pub_keyblock; node; node = node->next ) {
2133         if( node->pkt->pkttype == PKT_USER_ID ) {
2134             uid = (node->flag & NODFLG_SELUID)? node->pkt->pkt.user_id : NULL;
2135         }
2136         else if( uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2137            int okay, valid, selfsig, inv_sig, no_key, other_err;
2138
2139             tty_printf("uid  ");
2140             tty_print_utf8_string( uid->name, uid->len );
2141             tty_printf("\n");
2142
2143            okay = inv_sig = no_key = other_err = 0;
2144             valid = print_and_check_one_sig( pub_keyblock, node,
2145                                             &inv_sig, &no_key, &other_err,
2146                                             &selfsig, 1 );
2147
2148            if( valid ) {
2149                okay = cpr_get_answer_yes_no_quit(
2150                    "keyedit.delsig.valid",
2151                    _("Delete this good signature? (y/N/q)"));
2152
2153                /* Only update trust if we delete a good signature.
2154                   The other two cases do not affect trust. */
2155                if(okay)
2156                  update_trust=1;
2157            }
2158            else if( inv_sig || other_err )
2159                okay = cpr_get_answer_yes_no_quit(
2160                    "keyedit.delsig.invalid",
2161                    _("Delete this invalid signature? (y/N/q)"));
2162            else if( no_key )
2163                okay = cpr_get_answer_yes_no_quit(
2164                    "keyedit.delsig.unknown",
2165                    _("Delete this unknown signature? (y/N/q)"));
2166
2167             if( okay == -1 )
2168                 break;
2169            if( okay && selfsig && !cpr_get_answer_is_yes(
2170                                "keyedit.delsig.selfsig",
2171                               _("Really delete this self-signature? (y/N)") ))
2172                 okay = 0;
2173             if( okay ) {
2174                 delete_kbnode( node );
2175                 changed++;
2176             }
2177
2178         }
2179         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2180             uid = NULL;
2181     }
2182
2183     if( changed ) {
2184         commit_kbnode( &pub_keyblock );
2185         tty_printf( changed == 1? _("Deleted %d signature.\n")
2186                                 : _("Deleted %d signatures.\n"), changed );
2187     }
2188     else
2189         tty_printf( _("Nothing deleted.\n") );
2190
2191     return changed;
2192 }
2193
2194
2195 /****************
2196  * Remove some of the secondary keys
2197  */
2198 static void
2199 menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
2200 {
2201     KBNODE node;
2202     int selected=0;
2203
2204     for( node = pub_keyblock; node; node = node->next ) {
2205         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
2206             selected = node->flag & NODFLG_SELKEY;
2207             if( selected ) {
2208                 delete_kbnode( node );
2209                 if( sec_keyblock ) {
2210                     KBNODE snode;
2211                     int s_selected = 0;
2212                     u32 ki[2];
2213
2214                     keyid_from_pk( node->pkt->pkt.public_key, ki );
2215                     for( snode = sec_keyblock; snode; snode = snode->next ) {
2216                         if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2217                             u32 ki2[2];
2218
2219                             keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
2220                             s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
2221                             if( s_selected )
2222                                 delete_kbnode( snode );
2223                         }
2224                         else if( s_selected
2225                                  && snode->pkt->pkttype == PKT_SIGNATURE )
2226                             delete_kbnode( snode );
2227                         else
2228                             s_selected = 0;
2229                     }
2230                 }
2231             }
2232         }
2233         else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
2234             delete_kbnode( node );
2235         else
2236             selected = 0;
2237     }
2238     commit_kbnode( &pub_keyblock );
2239     if( sec_keyblock )
2240         commit_kbnode( &sec_keyblock );
2241
2242     /* No need to set update_trust here since signing keys no longer
2243        are used to certify other keys, so there is no change in trust
2244        when revoking/removing them */
2245 }
2246
2247
2248 /****************
2249  * Ask for a new revoker, do the selfsignature and put it into
2250  * both keyblocks.
2251  * Return true if there is a new revoker
2252  */
2253 static int
2254 menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
2255 {
2256   PKT_public_key *pk=NULL,*revoker_pk=NULL;
2257   PKT_secret_key *sk=NULL;
2258   PKT_signature *sig=NULL;
2259   PACKET *pkt;
2260   struct revocation_key revkey;
2261   size_t fprlen;
2262   int rc;
2263
2264   assert(pub_keyblock->pkt->pkttype==PKT_PUBLIC_KEY);
2265   assert(sec_keyblock->pkt->pkttype==PKT_SECRET_KEY);
2266
2267   pk=pub_keyblock->pkt->pkt.public_key;
2268
2269   if(pk->numrevkeys==0 && pk->version==3)
2270     {
2271       /* It is legal but bad for compatibility to add a revoker to a
2272          v3 key as it means that PGP2 will not be able to use that key
2273          anymore.  Also, PGP may not expect a revoker on a v3 key.
2274          Don't bother to ask this if the key already has a revoker -
2275          any damage has already been done at that point. -dms */
2276       if(opt.expert)
2277         {
2278           tty_printf(_("WARNING: This is a PGP 2.x-style key.  "
2279                        "Adding a designated revoker may cause\n"
2280                        "         some versions of PGP to reject this key.\n"));
2281
2282           if(!cpr_get_answer_is_yes("keyedit.v3_revoker.okay",
2283                                     _("Are you sure you still want "
2284                                       "to add it? (y/N) ")))
2285             return 0;
2286         }
2287       else
2288         {
2289           tty_printf(_("You may not add a designated revoker to "
2290                        "a PGP 2.x-style key.\n"));
2291           return 0;
2292         }
2293     }
2294
2295   sk=copy_secret_key(NULL,sec_keyblock->pkt->pkt.secret_key);
2296
2297   for(;;)
2298     {
2299       char *answer;
2300       u32 keyid[2];
2301       char *p;
2302       size_t n;
2303
2304       if(revoker_pk)
2305         free_public_key(revoker_pk);
2306
2307       revoker_pk=m_alloc_clear(sizeof(*revoker_pk));
2308
2309       tty_printf("\n");
2310
2311       answer=cpr_get_utf8("keyedit.add_revoker",
2312                           _("Enter the user ID of the designated revoker: "));
2313       if(answer[0]=='\0' || answer[0]=='\004')
2314         goto fail;
2315
2316       rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL);
2317
2318       if(rc)
2319         {
2320           log_error (_("key `%s' not found: %s\n"),answer,g10_errstr(rc));
2321           continue;
2322         }
2323
2324       fingerprint_from_pk(revoker_pk,revkey.fpr,&fprlen);
2325       if(fprlen!=20)
2326         {
2327           log_error(_("cannot appoint a PGP 2.x style key as a "
2328                       "designated revoker\n"));
2329           continue;
2330         }
2331
2332       revkey.class=0x80;
2333       if(sensitive)
2334         revkey.class|=0x40;
2335       revkey.algid=revoker_pk->pubkey_algo;
2336
2337       if(cmp_public_keys(revoker_pk,pk)==0)
2338         {
2339           /* This actually causes no harm (after all, a key that
2340              designates itself as a revoker is the same as a
2341              regular key), but it's easy enough to check. */
2342           log_error(_("you cannot appoint a key as its own "
2343                       "designated revoker\n"));
2344
2345           continue;
2346         }
2347
2348       keyid_from_pk(pk,NULL);
2349
2350       /* Does this revkey already exist? */
2351       if(!pk->revkey && pk->numrevkeys)
2352         BUG();
2353       else
2354         {
2355           int i;
2356
2357           for(i=0;i<pk->numrevkeys;i++)
2358             {
2359               if(memcmp(&pk->revkey[i],&revkey,
2360                         sizeof(struct revocation_key))==0)
2361                 {
2362                   char buf[50];
2363
2364                   log_error(_("this key has already been designated "
2365                               "as a revoker\n"));
2366
2367                   sprintf(buf,"%08lX%08lX",
2368                           (ulong)pk->keyid[0],(ulong)pk->keyid[1]);
2369                   write_status_text(STATUS_ALREADY_SIGNED,buf);
2370
2371                   break;
2372                 }
2373             }
2374
2375           if(i<pk->numrevkeys)
2376             continue;
2377         }
2378
2379       keyid_from_pk(revoker_pk,keyid);
2380
2381       tty_printf("\npub   %4u%c/%08lX %s   ",
2382                  nbits_from_pk( revoker_pk ),
2383                  pubkey_letter( revoker_pk->pubkey_algo ),
2384                  (ulong)keyid[1], datestr_from_pk(pk) );
2385
2386       p = get_user_id( keyid, &n );
2387       tty_print_utf8_string( p, n );
2388       m_free(p);
2389       tty_printf("\n");
2390       print_fingerprint(revoker_pk,NULL,2);
2391       tty_printf("\n");
2392
2393       tty_printf("WARNING: appointing a key as a designated revoker "
2394                  "cannot be undone!\n");
2395
2396       tty_printf("\n");
2397
2398       if(!cpr_get_answer_is_yes("keyedit.add_revoker.okay",
2399                                 "Are you sure you want to appoint this "
2400                                 "key as a designated revoker? (y/N): "))
2401         continue;
2402
2403       free_public_key(revoker_pk);
2404       revoker_pk=NULL;
2405       break;
2406     }
2407
2408   /* The 1F signature must be at least v4 to carry the revocation key
2409      subpacket. */
2410   rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x1F, 0, 4, 0, 0,
2411                            keygen_add_revkey,&revkey );
2412   if( rc )
2413     {
2414       log_error("signing failed: %s\n", g10_errstr(rc) );
2415       goto fail;
2416     }
2417
2418   free_secret_key(sk);
2419   sk=NULL;
2420
2421   /* insert into secret keyblock */
2422   pkt = m_alloc_clear( sizeof *pkt );
2423   pkt->pkttype = PKT_SIGNATURE;
2424   pkt->pkt.signature = copy_signature(NULL, sig);
2425   insert_kbnode( sec_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2426
2427   /* insert into public keyblock */
2428   pkt = m_alloc_clear( sizeof *pkt );
2429   pkt->pkttype = PKT_SIGNATURE;
2430   pkt->pkt.signature = sig;
2431   insert_kbnode( pub_keyblock, new_kbnode(pkt), PKT_SIGNATURE );
2432
2433   return 1;
2434
2435  fail:
2436   if(sk)
2437     free_secret_key(sk);
2438   if(sig)
2439     free_seckey_enc(sig);
2440   if(revoker_pk)
2441     free_public_key(revoker_pk);
2442
2443   return 0;
2444 }
2445
2446
2447 static int
2448 menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
2449 {
2450     int n1, signumber, rc;
2451     u32 expiredate;
2452     int mainkey=0;
2453     PKT_secret_key *sk;    /* copy of the main sk */
2454     PKT_public_key *main_pk, *sub_pk;
2455     PKT_user_id *uid;
2456     KBNODE node;
2457     u32 keyid[2];
2458
2459     if( count_selected_keys( sec_keyblock ) ) {
2460         tty_printf(_("Please remove selections from the secret keys.\n"));
2461         return 0;
2462     }
2463
2464     n1 = count_selected_keys( pub_keyblock );
2465     if( n1 > 1 ) {
2466         tty_printf(_("Please select at most one secondary key.\n"));
2467         return 0;
2468     }
2469     else if( n1 )
2470         tty_printf(_("Changing expiration time for a secondary key.\n"));
2471     else {
2472         tty_printf(_("Changing expiration time for the primary key.\n"));
2473         mainkey=1;
2474     }
2475
2476     expiredate = ask_expiredate();
2477     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2478     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2479
2480     /* Now we can actually change the self signature(s) */
2481     main_pk = sub_pk = NULL;
2482     uid = NULL;
2483     signumber = 0;
2484     for( node=pub_keyblock; node; node = node->next ) {
2485         if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2486             main_pk = node->pkt->pkt.public_key;
2487             keyid_from_pk( main_pk, keyid );
2488             main_pk->expiredate = expiredate;
2489         }
2490         else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2491                  && (node->flag & NODFLG_SELKEY ) ) {
2492             sub_pk = node->pkt->pkt.public_key;
2493             sub_pk->expiredate = expiredate;
2494         }
2495         else if( node->pkt->pkttype == PKT_USER_ID )
2496             uid = node->pkt->pkt.user_id;
2497         else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE
2498                  && ( mainkey || sub_pk ) ) {
2499             PKT_signature *sig = node->pkt->pkt.signature;
2500             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2501                 && (    (mainkey && uid && (sig->sig_class&~3) == 0x10)
2502                      || (!mainkey && sig->sig_class == 0x18)  ) ) {
2503                 /* this is a selfsignature which is to be replaced */
2504                 PKT_signature *newsig;
2505                 PACKET *newpkt;
2506                 KBNODE sn;
2507                 int signumber2 = 0;
2508
2509                 signumber++;
2510
2511                 if( (mainkey && main_pk->version < 4)
2512                     || (!mainkey && sub_pk->version < 4 ) ) {
2513                     log_info(_(
2514                         "You can't change the expiration date of a v3 key\n"));
2515                     free_secret_key( sk );
2516                     return 0;
2517                 }
2518
2519                 /* find the corresponding secret self-signature */
2520                 for( sn=sec_keyblock; sn; sn = sn->next ) {
2521                     if( sn->pkt->pkttype == PKT_SIGNATURE ) {
2522                         PKT_signature *b = sn->pkt->pkt.signature;
2523                         if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
2524                             && sig->sig_class == b->sig_class
2525                             && ++signumber2 == signumber )
2526                             break;
2527                     }
2528                 }
2529                 if( !sn )
2530                     log_info(_("No corresponding signature in secret ring\n"));
2531
2532                 /* create new self signature */
2533                 if( mainkey )
2534                     rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
2535                                              sk, 0x13, 0, 0, 0, 0,
2536                                              keygen_add_std_prefs, main_pk );
2537                 else
2538                     rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
2539                                              sk, 0x18, 0, 0, 0, 0,
2540                                              keygen_add_key_expire, sub_pk );
2541                 if( rc ) {
2542                     log_error("make_keysig_packet failed: %s\n",
2543                                                     g10_errstr(rc));
2544                     free_secret_key( sk );
2545                     return 0;
2546                 }
2547                 /* replace the packet */
2548                 newpkt = m_alloc_clear( sizeof *newpkt );
2549                 newpkt->pkttype = PKT_SIGNATURE;
2550                 newpkt->pkt.signature = newsig;
2551                 free_packet( node->pkt );
2552                 m_free( node->pkt );
2553                 node->pkt = newpkt;
2554                 if( sn ) {
2555                     newpkt = m_alloc_clear( sizeof *newpkt );
2556                     newpkt->pkttype = PKT_SIGNATURE;
2557                     newpkt->pkt.signature = copy_signature( NULL, newsig );
2558                     free_packet( sn->pkt );
2559                     m_free( sn->pkt );
2560                     sn->pkt = newpkt;
2561                 }
2562                 sub_pk = NULL;
2563             }
2564         }
2565     }
2566
2567     free_secret_key( sk );
2568     update_trust=1;
2569     return 1;
2570 }
2571
2572 static int
2573 change_primary_uid_cb ( PKT_signature *sig, void *opaque )
2574 {
2575     byte buf[1];
2576
2577     /* first clear all primary uid flags so that we are sure none are
2578      * lingering around */
2579     delete_sig_subpkt (sig->hashed,   SIGSUBPKT_PRIMARY_UID);
2580     delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID);
2581
2582     /* if opaque is set,we want to set the primary id */
2583     if (opaque) { 
2584         buf[0] = 1;
2585         build_sig_subpkt (sig, SIGSUBPKT_PRIMARY_UID, buf, 1 );
2586     }
2587
2588     return 0;
2589 }
2590
2591
2592 /*
2593  * Set the primary uid flag for the selected UID.  We will also reset
2594  * all other primary uid flags.  For this to work with have to update
2595  * all the signature timestamps.  If we would do this with the current
2596  * time, we lose quite a lot of information, so we use a a kludge to
2597  * do this: Just increment the timestamp by one second which is
2598  * sufficient to updated a signature during import.
2599  */
2600 static int
2601 menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
2602 {
2603     PKT_secret_key *sk;    /* copy of the main sk */
2604     PKT_public_key *main_pk;
2605     PKT_user_id *uid;
2606     KBNODE node;
2607     u32 keyid[2];
2608     int selected;
2609     int attribute = 0;
2610     int modified = 0;
2611
2612     if ( count_selected_uids (pub_keyblock) != 1 ) {
2613         tty_printf(_("Please select exactly one user ID.\n"));
2614         return 0;
2615     }
2616
2617     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2618     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2619
2620     /* Now we can actually change the self signature(s) */
2621     main_pk = NULL;
2622     uid = NULL;
2623     selected = 0;
2624
2625     /* Is our selected uid an attribute packet? */
2626     for ( node=pub_keyblock; node; node = node->next )
2627       if (node->pkt->pkttype == PKT_USER_ID && node->flag & NODFLG_SELUID)
2628         attribute = (node->pkt->pkt.user_id->attrib_data!=NULL);
2629
2630     for ( node=pub_keyblock; node; node = node->next ) {
2631         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2632             break; /* ready */
2633
2634         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2635             main_pk = node->pkt->pkt.public_key;
2636             keyid_from_pk( main_pk, keyid );
2637         }
2638         else if ( node->pkt->pkttype == PKT_USER_ID ) {
2639             uid = node->pkt->pkt.user_id;
2640             selected = node->flag & NODFLG_SELUID;
2641         }
2642         else if ( main_pk && uid && node->pkt->pkttype == PKT_SIGNATURE ) {
2643             PKT_signature *sig = node->pkt->pkt.signature;
2644             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2645                 && (uid && (sig->sig_class&~3) == 0x10)
2646                 && attribute == (uid->attrib_data!=NULL)) {
2647               if(sig->version < 4) {
2648                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
2649
2650                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
2651                          user);
2652                 m_free(user);
2653               }
2654               else {
2655                 /* This is a selfsignature which is to be replaced.
2656                    We can just ignore v3 signatures because they are
2657                    not able to carry the primary ID flag.  We also
2658                    ignore self-sigs on user IDs that are not of the
2659                    same type that we are making primary.  That is, if
2660                    we are making a user ID primary, we alter user IDs.
2661                    If we are making an attribute packet primary, we
2662                    alter attribute packets. */
2663
2664                 /* FIXME: We must make sure that we only have one
2665                    self-signature per user ID here (not counting
2666                    revocations) */
2667                 PKT_signature *newsig;
2668                 PACKET *newpkt;
2669                 const byte *p;
2670                 int action;
2671
2672                 /* see whether this signature has the primary UID flag */
2673                 p = parse_sig_subpkt (sig->hashed,
2674                                       SIGSUBPKT_PRIMARY_UID, NULL );
2675                 if ( !p )
2676                     p = parse_sig_subpkt (sig->unhashed,
2677                                           SIGSUBPKT_PRIMARY_UID, NULL );
2678                 if ( p && *p ) /* yes */
2679                     action = selected? 0 : -1;
2680                 else /* no */
2681                     action = selected? 1 : 0;
2682
2683                 if (action) {
2684                     int rc = update_keysig_packet (&newsig, sig,
2685                                                main_pk, uid, 
2686                                                sk,
2687                                                change_primary_uid_cb,
2688                                                action > 0? "x":NULL );
2689                     if( rc ) {
2690                         log_error ("update_keysig_packet failed: %s\n",
2691                                    g10_errstr(rc));
2692                         free_secret_key( sk );
2693                         return 0;
2694                     }
2695                     /* replace the packet */
2696                     newpkt = m_alloc_clear( sizeof *newpkt );
2697                     newpkt->pkttype = PKT_SIGNATURE;
2698                     newpkt->pkt.signature = newsig;
2699                     free_packet( node->pkt );
2700                     m_free( node->pkt );
2701                     node->pkt = newpkt;
2702                     modified = 1;
2703                 }
2704               }
2705             }
2706         }
2707     }
2708
2709     free_secret_key( sk );
2710     return modified;
2711 }
2712
2713
2714 /* 
2715  * Set preferences to new values for the selected user IDs
2716  */
2717 static int
2718 menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
2719 {
2720     PKT_secret_key *sk;    /* copy of the main sk */
2721     PKT_public_key *main_pk;
2722     PKT_user_id *uid;
2723     KBNODE node;
2724     u32 keyid[2];
2725     int selected, select_all;
2726     int modified = 0;
2727
2728     select_all = !count_selected_uids (pub_keyblock);
2729
2730     node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
2731     sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
2732
2733     /* Now we can actually change the self signature(s) */
2734     main_pk = NULL;
2735     uid = NULL;
2736     selected = 0;
2737     for ( node=pub_keyblock; node; node = node->next ) {
2738         if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
2739             break; /* ready */
2740
2741         if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
2742             main_pk = node->pkt->pkt.public_key;
2743             keyid_from_pk( main_pk, keyid );
2744         }
2745         else if ( node->pkt->pkttype == PKT_USER_ID ) {
2746             uid = node->pkt->pkt.user_id;
2747             selected = select_all || (node->flag & NODFLG_SELUID);
2748         }
2749         else if ( main_pk && uid && selected
2750                   && node->pkt->pkttype == PKT_SIGNATURE ) {
2751             PKT_signature *sig = node->pkt->pkt.signature;
2752             if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
2753                  && (uid && (sig->sig_class&~3) == 0x10) ) {
2754               if( sig->version < 4 ) {
2755                 char *user=utf8_to_native(uid->name,strlen(uid->name),0);
2756
2757                 log_info(_("skipping v3 self-signature on user id \"%s\"\n"),
2758                          user);
2759                 m_free(user);
2760               }
2761               else {
2762                 /* This is a selfsignature which is to be replaced 
2763                  * We have to ignore v3 signatures because they are
2764                  * not able to carry the preferences */
2765                 PKT_signature *newsig;
2766                 PACKET *newpkt;
2767                 int rc;
2768
2769                 rc = update_keysig_packet (&newsig, sig,
2770                                            main_pk, uid, 
2771                                            sk,
2772                                            keygen_upd_std_prefs,
2773                                            NULL );
2774                 if( rc ) {
2775                     log_error ("update_keysig_packet failed: %s\n",
2776                                g10_errstr(rc));
2777                     free_secret_key( sk );
2778                     return 0;
2779                 }
2780                 /* replace the packet */
2781                 newpkt = m_alloc_clear( sizeof *newpkt );
2782                 newpkt->pkttype = PKT_SIGNATURE;
2783                 newpkt->pkt.signature = newsig;
2784                 free_packet( node->pkt );
2785                 m_free( node->pkt );
2786                 node->pkt = newpkt;
2787                 modified = 1;
2788               }
2789             }
2790         }
2791     }
2792     
2793     free_secret_key( sk );
2794     return modified;
2795 }
2796
2797
2798 /****************
2799  * Select one user id or remove all selection if index is 0.
2800  * Returns: True if the selection changed;
2801  */
2802 static int
2803 menu_select_uid( KBNODE keyblock, int idx )
2804 {
2805     KBNODE node;
2806     int i;
2807
2808     /* first check that the index is valid */
2809     if( idx ) {
2810         for( i=0, node = keyblock; node; node = node->next ) {
2811             if( node->pkt->pkttype == PKT_USER_ID ) {
2812                 if( ++i == idx )
2813                     break;
2814             }
2815         }
2816         if( !node ) {
2817             tty_printf(_("No user ID with index %d\n"), idx );
2818             return 0;
2819         }
2820     }
2821     else { /* reset all */
2822         for( i=0, node = keyblock; node; node = node->next ) {
2823             if( node->pkt->pkttype == PKT_USER_ID )
2824                 node->flag &= ~NODFLG_SELUID;
2825         }
2826         return 1;
2827     }
2828     /* and toggle the new index */
2829     for( i=0, node = keyblock; node; node = node->next ) {
2830         if( node->pkt->pkttype == PKT_USER_ID ) {
2831             if( ++i == idx ) {
2832                 if( (node->flag & NODFLG_SELUID) )
2833                     node->flag &= ~NODFLG_SELUID;
2834                 else
2835                     node->flag |= NODFLG_SELUID;
2836             }
2837         }
2838     }
2839
2840     return 1;
2841 }
2842
2843 /****************
2844  * Select secondary keys
2845  * Returns: True if the selection changed;
2846  */
2847 static int
2848 menu_select_key( KBNODE keyblock, int idx )
2849 {
2850     KBNODE node;
2851     int i;
2852
2853     /* first check that the index is valid */
2854     if( idx ) {
2855         for( i=0, node = keyblock; node; node = node->next ) {
2856             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2857                 || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2858                 if( ++i == idx )
2859                     break;
2860             }
2861         }
2862         if( !node ) {
2863             tty_printf(_("No secondary key with index %d\n"), idx );
2864             return 0;
2865         }
2866     }
2867     else { /* reset all */
2868         for( i=0, node = keyblock; node; node = node->next ) {
2869             if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2870                 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
2871                 node->flag &= ~NODFLG_SELKEY;
2872         }
2873         return 1;
2874     }
2875     /* and set the new index */
2876     for( i=0, node = keyblock; node; node = node->next ) {
2877         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2878             || node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
2879             if( ++i == idx ) {
2880                 if( (node->flag & NODFLG_SELKEY) )
2881                     node->flag &= ~NODFLG_SELKEY;
2882                 else
2883                     node->flag |= NODFLG_SELKEY;
2884             }
2885         }
2886     }
2887
2888     return 1;
2889 }
2890
2891
2892 static int
2893 count_uids_with_flag( KBNODE keyblock, unsigned flag )
2894 {
2895     KBNODE node;
2896     int i=0;
2897
2898     for( node = keyblock; node; node = node->next )
2899         if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
2900             i++;
2901     return i;
2902 }
2903
2904 static int
2905 count_keys_with_flag( KBNODE keyblock, unsigned flag )
2906 {
2907     KBNODE node;
2908     int i=0;
2909
2910     for( node = keyblock; node; node = node->next )
2911         if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2912               || node->pkt->pkttype == PKT_SECRET_SUBKEY)
2913             && (node->flag & flag) )
2914             i++;
2915     return i;
2916 }
2917
2918 static int
2919 count_uids( KBNODE keyblock )
2920 {
2921     KBNODE node;
2922     int i=0;
2923
2924     for( node = keyblock; node; node = node->next )
2925         if( node->pkt->pkttype == PKT_USER_ID )
2926             i++;
2927     return i;
2928 }
2929
2930
2931 /****************
2932  * Returns true if there is at least one selected user id
2933  */
2934 static int
2935 count_selected_uids( KBNODE keyblock )
2936 {
2937     return count_uids_with_flag( keyblock, NODFLG_SELUID);
2938 }
2939
2940 static int
2941 count_selected_keys( KBNODE keyblock )
2942 {
2943     return count_keys_with_flag( keyblock, NODFLG_SELKEY);
2944 }
2945
2946 /* returns how many real (i.e. not attribute) uids are unmarked */
2947 static int
2948 real_uids_left( KBNODE keyblock )
2949 {
2950   KBNODE node;
2951   int real=0;
2952
2953   for(node=keyblock;node;node=node->next)
2954     if(node->pkt->pkttype==PKT_USER_ID && !(node->flag&NODFLG_SELUID) &&
2955        !node->pkt->pkt.user_id->attrib_data)
2956       real++;
2957
2958   return real;
2959 }
2960
2961 /*
2962  * Ask whether the signature should be revoked.  If the user commits this,
2963  * flag bit MARK_A is set on the signature and the user ID.
2964  */
2965 static void
2966 ask_revoke_sig( KBNODE keyblock, KBNODE node )
2967 {
2968     int doit=0;
2969     PKT_signature *sig = node->pkt->pkt.signature;
2970     KBNODE unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
2971
2972     if( !unode ) {
2973         log_error("Oops: no user ID for signature\n");
2974         return;
2975     }
2976
2977     tty_printf(_("user ID: \""));
2978     tty_print_utf8_string( unode->pkt->pkt.user_id->name,
2979                            unode->pkt->pkt.user_id->len );
2980
2981     if(sig->flags.exportable)
2982       tty_printf(_("\"\nsigned with your key %08lX at %s\n"),
2983                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
2984     else
2985       tty_printf(_("\"\nlocally signed with your key %08lX at %s\n"),
2986                  (ulong)sig->keyid[1], datestr_from_sig(sig) );
2987
2988     if(sig->flags.expired)
2989       {
2990         tty_printf(_("This signature expired on %s.\n"),
2991                    expirestr_from_sig(sig));
2992         /* Use a different question so we can have different help text */
2993         doit=cpr_get_answer_is_yes("ask_revoke_sig.expired",
2994                         _("Are you sure you still want to revoke it? (y/N) "));
2995       }
2996     else
2997       doit=cpr_get_answer_is_yes("ask_revoke_sig.one",
2998               _("Create a revocation certificate for this signature? (y/N) "));
2999
3000     if(doit) {
3001       node->flag |= NODFLG_MARK_A;
3002       unode->flag |= NODFLG_MARK_A;
3003     }
3004 }
3005
3006 /****************
3007  * Display all user ids of the current public key together with signatures
3008  * done by one of our keys.  Then walk over all this sigs and ask the user
3009  * whether he wants to revoke this signature.
3010  * Return: True when the keyblock has changed.
3011  */
3012 static int
3013 menu_revsig( KBNODE keyblock )
3014 {
3015     PKT_signature *sig;
3016     PKT_public_key *primary_pk;
3017     KBNODE node;
3018     int changed = 0;
3019     int rc, any, skip=1, all=!count_selected_uids(keyblock);
3020     struct revocation_reason_info *reason = NULL;
3021
3022     /* FIXME: detect duplicates here  */
3023     tty_printf(_("You have signed these user IDs:\n"));
3024     for( node = keyblock; node; node = node->next ) {
3025         node->flag &= ~(NODFLG_SELSIG | NODFLG_MARK_A);
3026         if( node->pkt->pkttype == PKT_USER_ID ) {
3027             if( node->flag&NODFLG_SELUID || all ) {
3028               PKT_user_id *uid = node->pkt->pkt.user_id;
3029               /* Hmmm: Should we show only UIDs with a signature? */
3030               tty_printf("     ");
3031               tty_print_utf8_string( uid->name, uid->len );
3032               tty_printf("\n");
3033               skip=0;
3034             }
3035             else
3036               skip=1;
3037         }
3038         else if( !skip && node->pkt->pkttype == PKT_SIGNATURE
3039                 && ((sig = node->pkt->pkt.signature),
3040                      !seckey_available(sig->keyid)  ) ) {
3041             if( (sig->sig_class&~3) == 0x10 ) {
3042                 tty_printf(_("   signed by %08lX at %s%s%s\n"),
3043                            (ulong)sig->keyid[1], datestr_from_sig(sig),
3044                            sig->flags.exportable?"":" (non-exportable)",
3045                            sig->flags.revocable?"":" (non-revocable)");
3046                 if(sig->flags.revocable)
3047                   node->flag |= NODFLG_SELSIG;
3048             }
3049             else if( sig->sig_class == 0x30 ) {
3050                 tty_printf(_("   revoked by %08lX at %s\n"),
3051                             (ulong)sig->keyid[1], datestr_from_sig(sig) );
3052             }
3053         }
3054     }
3055
3056     /* ask */
3057     for( node = keyblock; node; node = node->next ) {
3058         if( !(node->flag & NODFLG_SELSIG) )
3059             continue;
3060         ask_revoke_sig( keyblock, node );
3061     }
3062
3063     /* present selected */
3064     any = 0;
3065     for( node = keyblock; node; node = node->next ) {
3066         if( !(node->flag & NODFLG_MARK_A) )
3067             continue;
3068         if( !any ) {
3069             any = 1;
3070             tty_printf(_("You are about to revoke these signatures:\n"));
3071         }
3072         if( node->pkt->pkttype == PKT_USER_ID ) {
3073             PKT_user_id *uid = node->pkt->pkt.user_id;
3074             tty_printf("     ");
3075             tty_print_utf8_string( uid->name, uid->len );
3076             tty_printf("\n");
3077         }
3078         else if( node->pkt->pkttype == PKT_SIGNATURE ) {
3079             sig = node->pkt->pkt.signature;
3080             tty_printf(_("   signed by %08lX at %s%s\n"),
3081                        (ulong)sig->keyid[1], datestr_from_sig(sig),
3082                        sig->flags.exportable?"":_(" (non-exportable)") );
3083         }
3084     }
3085     if( !any )
3086         return 0; /* none selected */
3087
3088     if( !cpr_get_answer_is_yes("ask_revoke_sig.okay",
3089          _("Really create the revocation certificates? (y/N) ")) )
3090         return 0; /* forget it */
3091
3092     reason = ask_revocation_reason( 0, 1, 0 );
3093     if( !reason ) { /* user decided to cancel */
3094         return 0;
3095     }
3096
3097     /* now we can sign the user ids */
3098   reloop: /* (must use this, because we are modifing the list) */
3099     primary_pk = keyblock->pkt->pkt.public_key;
3100     for( node=keyblock; node; node = node->next ) {
3101         KBNODE unode;
3102         PACKET *pkt;
3103         struct sign_attrib attrib;
3104         PKT_secret_key *sk;
3105
3106         if( !(node->flag & NODFLG_MARK_A)
3107             || node->pkt->pkttype != PKT_SIGNATURE )
3108             continue;
3109         unode = find_prev_kbnode( keyblock, node, PKT_USER_ID );
3110         assert( unode ); /* we already checked this */
3111
3112         memset( &attrib, 0, sizeof attrib );
3113         attrib.reason = reason;
3114         attrib.non_exportable=!node->pkt->pkt.signature->flags.exportable;
3115
3116         node->flag &= ~NODFLG_MARK_A;
3117         sk = m_alloc_secure_clear( sizeof *sk );
3118         if( get_seckey( sk, node->pkt->pkt.signature->keyid ) ) {
3119             log_info(_("no secret key\n"));
3120             continue;
3121         }
3122         rc = make_keysig_packet( &sig, primary_pk,
3123                                        unode->pkt->pkt.user_id,
3124                                        NULL,
3125                                        sk,
3126                                        0x30, 0, 0, 0, 0,
3127                                        sign_mk_attrib,
3128                                        &attrib );
3129         free_secret_key(sk);
3130         if( rc ) {
3131             log_error(_("signing failed: %s\n"), g10_errstr(rc));
3132             release_revocation_reason_info( reason );
3133             return changed;
3134         }
3135         changed = 1; /* we changed the keyblock */
3136         update_trust = 1;
3137         /* Are we revoking our own uid? */
3138         if(primary_pk->keyid[0]==sig->keyid[0] &&
3139            primary_pk->keyid[1]==sig->keyid[1])
3140           unode->pkt->pkt.user_id->is_revoked=1;
3141         pkt = m_alloc_clear( sizeof *pkt );
3142         pkt->pkttype = PKT_SIGNATURE;
3143         pkt->pkt.signature = sig;
3144         insert_kbnode( unode, new_kbnode(pkt), 0 );
3145         goto reloop;
3146     }
3147
3148     release_revocation_reason_info( reason );
3149     return changed;
3150 }
3151
3152 /****************
3153  * Revoke some of the secondary keys.
3154  * Hmmm: Should we add a revocation to the secret keyring too?
3155  *       Does its all make sense to duplicate most of the information?
3156  */
3157 static int
3158 menu_revkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
3159 {
3160     PKT_public_key *mainpk;
3161     KBNODE node;
3162     int changed = 0;
3163     int rc;
3164     struct revocation_reason_info *reason = NULL;
3165
3166     reason = ask_revocation_reason( 1, 0, 0 );
3167     if( !reason ) { /* user decided to cancel */
3168         return 0;
3169     }
3170
3171
3172   reloop: /* (better this way because we are modifing the keyring) */
3173     mainpk = pub_keyblock->pkt->pkt.public_key;
3174     for( node = pub_keyblock; node; node = node->next ) {
3175         if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
3176             && (node->flag & NODFLG_SELKEY) ) {
3177             PACKET *pkt;
3178             PKT_signature *sig;
3179             PKT_secret_key *sk;
3180             PKT_public_key *subpk = node->pkt->pkt.public_key;
3181             struct sign_attrib attrib;
3182
3183             memset( &attrib, 0, sizeof attrib );
3184             attrib.reason = reason;
3185
3186             node->flag &= ~NODFLG_SELKEY;
3187             sk = copy_secret_key( NULL, sec_keyblock->pkt->pkt.secret_key );
3188             rc = make_keysig_packet( &sig, mainpk, NULL, subpk, sk,
3189                                      0x28, 0, 0, 0, 0,
3190                                      sign_mk_attrib, &attrib );
3191             free_secret_key(sk);
3192             if( rc ) {
3193                 log_error(_("signing failed: %s\n"), g10_errstr(rc));
3194                 release_revocation_reason_info( reason );
3195                 return changed;
3196             }
3197             changed = 1; /* we changed the keyblock */
3198
3199             pkt = m_alloc_clear( sizeof *pkt );
3200             pkt->pkttype = PKT_SIGNATURE;
3201             pkt->pkt.signature = sig;
3202             insert_kbnode( node, new_kbnode(pkt), 0 );
3203             goto reloop;
3204         }
3205     }
3206     commit_kbnode( &pub_keyblock );
3207     /*commit_kbnode( &sec_keyblock );*/
3208
3209     /* No need to set update_trust here since signing keys no longer
3210        are used to certify other keys, so there is no change in trust
3211        when revoking/removing them */
3212
3213     release_revocation_reason_info( reason );
3214     return changed;
3215 }
3216
3217
3218 static int
3219 enable_disable_key( KBNODE keyblock, int disable )
3220 {
3221     PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY )
3222                             ->pkt->pkt.public_key;
3223     unsigned int trust, newtrust;
3224
3225     trust = newtrust = get_ownertrust (pk);
3226     newtrust &= ~TRUST_FLAG_DISABLED;
3227     if( disable )
3228         newtrust |= TRUST_FLAG_DISABLED;
3229     if( trust == newtrust )
3230         return 0; /* already in that state */
3231     update_ownertrust(pk, newtrust );
3232     return 0;
3233 }
3234
3235
3236 static void
3237 menu_showphoto( KBNODE keyblock )
3238 {
3239   KBNODE node;
3240   int select_all = !count_selected_uids(keyblock);
3241   int count=0;
3242   PKT_public_key *pk=NULL;
3243   u32 keyid[2];
3244
3245   /* Look for the public key first.  We have to be really, really,
3246      explicit as to which photo this is, and what key it is a UID on
3247      since people may want to sign it. */
3248
3249   for( node = keyblock; node; node = node->next )
3250     {
3251       if( node->pkt->pkttype == PKT_PUBLIC_KEY )
3252         {
3253           pk = node->pkt->pkt.public_key;
3254           keyid_from_pk(pk, keyid);
3255         }
3256       else if( node->pkt->pkttype == PKT_USER_ID )
3257         {
3258           PKT_user_id *uid = node->pkt->pkt.user_id;
3259           count++;
3260
3261           if((select_all || (node->flag & NODFLG_SELUID)) &&
3262              uid->attribs!=NULL)
3263             {
3264               int i;
3265
3266               for(i=0;i<uid->numattribs;i++)
3267                 {
3268                   byte type;
3269                   u32 size;
3270
3271                   if(uid->attribs[i].type==ATTRIB_IMAGE &&
3272                      parse_image_header(&uid->attribs[i],&type,&size))
3273                     {
3274                       tty_printf(_("Displaying %s photo ID of size %ld for "
3275                                    "key 0x%08lX (uid %d)\n"),
3276                                  image_type_to_string(type,1),
3277                                  (ulong)size,(ulong)keyid[1],count);
3278                       show_photos(&uid->attribs[i],1,pk,NULL);
3279                     }
3280                 }
3281             }
3282         }
3283     }
3284 }