* trustdb.h, keyedit.c (keyedit_menu, menu_select_uid_namehash): Allow
[gnupg.git] / g10 / revoke.c
1 /* revoke.c
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2004 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <ctype.h>
29
30 #include "options.h"
31 #include "packet.h"
32 #include "errors.h"
33 #include "keydb.h"
34 #include "memory.h"
35 #include "util.h"
36 #include "main.h"
37 #include "ttyio.h"
38 #include "status.h"
39 #include "i18n.h"
40
41
42 struct revocation_reason_info {
43     int code;
44     char *desc;
45 };
46
47
48 int
49 revocation_reason_build_cb( PKT_signature *sig, void *opaque )
50 {
51     struct revocation_reason_info *reason = opaque;
52     char *ud = NULL;
53     byte *buffer;
54     size_t buflen = 1;
55
56     if(!reason)
57       return 0;
58
59     if( reason->desc ) {
60         ud = native_to_utf8( reason->desc );
61         buflen += strlen(ud);
62     }
63     buffer = m_alloc( buflen );
64     *buffer = reason->code;
65     if( ud ) {
66         memcpy(buffer+1, ud, strlen(ud) );
67         m_free( ud );
68     }
69
70     build_sig_subpkt( sig, SIGSUBPKT_REVOC_REASON, buffer, buflen );
71     m_free( buffer );
72     return 0;
73 }
74
75 /* Outputs a minimal pk (as defined by 2440) from a keyblock.  A
76    minimal pk consists of the public key packet and a user ID.  We try
77    and pick a user ID that has a uid signature, and include it if
78    possible. */
79 static int
80 export_minimal_pk(IOBUF out,KBNODE keyblock,
81                   PKT_signature *revsig,PKT_signature *revkey)
82 {
83   KBNODE node;
84   PACKET pkt;
85   PKT_user_id *uid=NULL;
86   PKT_signature *selfsig=NULL;
87   u32 keyid[2];
88   int rc;
89
90   node=find_kbnode(keyblock,PKT_PUBLIC_KEY);
91   if(!node)
92     {
93       log_error("key incomplete\n");
94       return G10ERR_GENERAL;
95     }
96
97   keyid_from_pk(node->pkt->pkt.public_key,keyid);
98
99   pkt=*node->pkt;
100   rc=build_packet(out,&pkt);
101   if(rc)
102     {
103       log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
104       return rc;
105     }
106
107   init_packet(&pkt);
108   pkt.pkttype=PKT_SIGNATURE;
109
110   /* the revocation itself, if any.  2440 likes this to come first. */
111   if(revsig)
112     {
113       pkt.pkt.signature=revsig;
114       rc=build_packet(out,&pkt);
115       if(rc)
116         {
117           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
118           return rc;
119         }
120     }
121
122   /* If a revkey in a 1F sig is present, include it too */
123   if(revkey)
124     {
125       pkt.pkt.signature=revkey;
126       rc=build_packet(out,&pkt);
127       if(rc)
128         {
129           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
130           return rc;
131         }
132     }
133
134   while(!selfsig)
135     {
136       KBNODE signode;
137
138       node=find_next_kbnode(node,PKT_USER_ID);
139       if(!node)
140         {
141           /* We're out of user IDs - none were self-signed. */
142           if(uid)
143             break;
144           else
145             {
146               log_error(_("key %s has no user IDs\n"),keystr(keyid));
147               return G10ERR_GENERAL;
148             }
149         }
150
151       if(node->pkt->pkt.user_id->attrib_data)
152         continue;
153
154       uid=node->pkt->pkt.user_id;
155       signode=node;
156
157       while((signode=find_next_kbnode(signode,PKT_SIGNATURE)))
158         {
159           if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
160              keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
161              IS_UID_SIG(signode->pkt->pkt.signature))
162             {
163               selfsig=signode->pkt->pkt.signature;
164               break;
165             }
166         }
167     }
168
169   pkt.pkttype=PKT_USER_ID;
170   pkt.pkt.user_id=uid;
171
172   rc=build_packet(out,&pkt);
173   if(rc)
174     {
175       log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
176       return rc;
177     }
178
179   if(selfsig)
180     {
181       pkt.pkttype=PKT_SIGNATURE;
182       pkt.pkt.signature=selfsig;
183
184       rc=build_packet(out,&pkt);
185       if(rc)
186         {
187           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
188           return rc;
189         }
190     }
191
192   return 0;
193 }
194
195 /****************
196  * Generate a revocation certificate for UNAME via a designated revoker
197  */
198 int
199 gen_desig_revoke( const char *uname )
200 {
201     int rc = 0;
202     armor_filter_context_t afx;
203     PKT_public_key *pk = NULL;
204     PKT_secret_key *sk = NULL;
205     PKT_signature *sig = NULL;
206     IOBUF out = NULL;
207     struct revocation_reason_info *reason = NULL;
208     KEYDB_HANDLE kdbhd;
209     KEYDB_SEARCH_DESC desc;
210     KBNODE keyblock=NULL,node;
211     u32 keyid[2];
212     int i,any=0;
213
214     if( opt.batch )
215       {
216         log_error(_("can't do this in batch mode\n"));
217         return G10ERR_GENERAL;
218       }
219
220     memset( &afx, 0, sizeof afx);
221
222     kdbhd = keydb_new (0);
223     classify_user_id (uname, &desc);
224     rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
225     if (rc) {
226         log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc));
227         goto leave;
228     }
229
230     rc = keydb_get_keyblock (kdbhd, &keyblock );
231     if( rc ) {
232         log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
233         goto leave;
234     }
235
236     /* To parse the revkeys */
237     merge_keys_and_selfsig(keyblock);
238
239     /* get the key from the keyblock */
240     node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
241     if( !node ) 
242       BUG ();
243
244     pk=node->pkt->pkt.public_key;
245
246     keyid_from_pk(pk,keyid);
247
248     /* Are we a designated revoker for this key? */
249
250     if(!pk->revkey && pk->numrevkeys)
251       BUG();
252
253     for(i=0;i<pk->numrevkeys;i++)
254       {
255         if(sk)
256           free_secret_key(sk);
257
258         sk=m_alloc_clear(sizeof(*sk));
259
260         rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
261
262         /* We have the revocation key */
263         if(!rc)
264           {
265             PKT_signature *revkey = NULL;
266
267             any = 1;
268
269             print_pubkey_info (NULL, pk);
270             tty_printf ("\n");
271
272             tty_printf (_("To be revoked by:\n"));
273             print_seckey_info (sk);
274
275             if(pk->revkey[i].class&0x40)
276               tty_printf(_("(This is a sensitive revocation key)\n"));
277             tty_printf("\n");
278
279             if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
280          _("Create a designated revocation certificate for this key? (y/N) ")))
281               continue;
282
283             /* get the reason for the revocation (this is always v4) */
284             reason = ask_revocation_reason( 1, 0, 1 );
285             if( !reason )
286               continue;
287
288             rc = check_secret_key( sk, 0 );
289             if( rc )
290               continue;
291
292             if( !opt.armor )
293               tty_printf(_("ASCII armored output forced.\n"));
294
295             if( (rc = open_outfile( NULL, 0, &out )) )
296               goto leave;
297
298             afx.what = 1;
299             afx.hdrlines = "Comment: A designated revocation certificate should follow\n";
300             iobuf_push_filter( out, armor_filter, &afx );
301
302             /* create it */
303             rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
304                                      0, 0, 0,
305                                      revocation_reason_build_cb, reason );
306             if( rc ) {
307               log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
308               goto leave;
309             }
310
311             /* Spit out a minimal pk as well, since otherwise there is
312                no way to know which key to attach this revocation to.
313                Also include the direct key signature that contains
314                this revocation key.  We're allowed to include
315                sensitive revocation keys along with a revocation, as
316                this may be the only time the recipient has seen it.
317                Note that this means that if we have multiple different
318                sensitive revocation keys in a given direct key
319                signature, we're going to include them all here.  This
320                is annoying, but the good outweighs the bad, since
321                without including this a sensitive revoker can't really
322                do their job.  People should not include multiple
323                sensitive revocation keys in one signature: 2440 says
324                "Note that it may be appropriate to isolate this
325                subpacket within a separate signature so that it is not
326                combined with other subpackets that need to be
327                exported." -dms */
328
329             while(!revkey)
330               {
331                 KBNODE signode;
332
333                 signode=find_next_kbnode(node,PKT_SIGNATURE);
334                 if(!signode)
335                   break;
336
337                 node=signode;
338
339                 if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
340                    keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
341                    IS_KEY_SIG(signode->pkt->pkt.signature))
342                   {
343                     int j;
344
345                     for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++)
346                       {
347                         if(pk->revkey[i].class==
348                            signode->pkt->pkt.signature->revkey[j]->class &&
349                            pk->revkey[i].algid==
350                            signode->pkt->pkt.signature->revkey[j]->algid &&
351                            memcmp(pk->revkey[i].fpr,
352                                   signode->pkt->pkt.signature->revkey[j]->fpr,
353                                   MAX_FINGERPRINT_LEN)==0)
354                           {
355                             revkey=signode->pkt->pkt.signature;
356                             break;
357                           }
358                       }
359                   }
360               }
361
362             if(!revkey)
363               BUG();
364
365             rc=export_minimal_pk(out,keyblock,sig,revkey);
366             if(rc)
367               goto leave;
368
369             /* and issue a usage notice */
370             tty_printf(_("Revocation certificate created.\n"));
371             break;
372           }
373       }
374
375     if(!any)
376       log_error(_("no revocation keys found for \"%s\"\n"),uname);
377
378   leave:
379     if( pk )
380         free_public_key( pk );
381     if( sk )
382         free_secret_key( sk );
383     if( sig )
384         free_seckey_enc( sig );
385
386     if( rc )
387         iobuf_cancel(out);
388     else
389         iobuf_close(out);
390     release_revocation_reason_info( reason );
391     return rc;
392 }
393
394
395 /****************
396  * Generate a revocation certificate for UNAME
397  */
398 int
399 gen_revoke( const char *uname )
400 {
401     int rc = 0;
402     armor_filter_context_t afx;
403     PACKET pkt;
404     PKT_secret_key *sk; /* used as pointer into a kbnode */
405     PKT_public_key *pk = NULL;
406     PKT_signature *sig = NULL;
407     u32 sk_keyid[2];
408     IOBUF out = NULL;
409     KBNODE keyblock = NULL, pub_keyblock = NULL;
410     KBNODE node;
411     KEYDB_HANDLE kdbhd;
412     struct revocation_reason_info *reason = NULL;
413     KEYDB_SEARCH_DESC desc;
414
415     if( opt.batch )
416       {
417         log_error(_("can't do this in batch mode\n"));
418         return G10ERR_GENERAL;
419       }
420
421     memset( &afx, 0, sizeof afx);
422     init_packet( &pkt );
423
424     /* search the userid: 
425      * We don't want the whole getkey stuff here but the entire keyblock
426      */
427     kdbhd = keydb_new (1);
428     classify_user_id (uname, &desc);
429     rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
430     if (rc)
431       {
432         log_error (_("secret key \"%s\" not found: %s\n"),
433                    uname, g10_errstr (rc));
434         goto leave;
435       }
436
437     rc = keydb_get_keyblock (kdbhd, &keyblock );
438     if( rc ) {
439         log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
440         goto leave;
441     }
442
443     /* get the keyid from the keyblock */
444     node = find_kbnode( keyblock, PKT_SECRET_KEY );
445     if( !node ) 
446         BUG ();
447
448     /* fixme: should make a function out of this stuff,
449      * it's used all over the source */
450     sk = node->pkt->pkt.secret_key;
451     keyid_from_sk( sk, sk_keyid );
452     print_seckey_info (sk);
453
454     pk = m_alloc_clear( sizeof *pk );
455
456     /* FIXME: We should get the public key direct from the secret one */
457
458     pub_keyblock=get_pubkeyblock(sk_keyid);
459     if(!pub_keyblock)
460       {
461         log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
462         goto leave;
463       }
464
465     node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
466     if(!node)
467       BUG();
468
469     pk=node->pkt->pkt.public_key;
470
471     if( cmp_public_secret_key( pk, sk ) ) {
472         log_error(_("public key does not match secret key!\n") );
473         rc = G10ERR_GENERAL;
474         goto leave;
475     }
476
477     tty_printf("\n");
478     if( !cpr_get_answer_is_yes("gen_revoke.okay",
479                   _("Create a revocation certificate for this key? (y/N) ")) )
480       {
481         rc = 0;
482         goto leave;
483       }
484
485     if(sk->version>=4 || opt.force_v4_certs) {
486       /* get the reason for the revocation */
487       reason = ask_revocation_reason( 1, 0, 1 );
488       if( !reason ) { /* user decided to cancel */
489         rc = 0;
490         goto leave;
491       }
492     }
493
494     switch( is_secret_key_protected( sk ) ) {
495       case -1:
496         log_error(_("unknown protection algorithm\n"));
497         rc = G10ERR_PUBKEY_ALGO;
498         break;
499       case 0:
500         tty_printf(_("NOTE: This key is not protected!\n"));
501         break;
502       default:
503         rc = check_secret_key( sk, 0 );
504         break;
505     }
506     if( rc )
507         goto leave;
508
509
510     if( !opt.armor )
511         tty_printf(_("ASCII armored output forced.\n"));
512
513     if( (rc = open_outfile( NULL, 0, &out )) )
514         goto leave;
515
516     afx.what = 1;
517     afx.hdrlines = "Comment: A revocation certificate should follow\n";
518     iobuf_push_filter( out, armor_filter, &afx );
519
520     /* create it */
521     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
522                              opt.force_v4_certs?4:0, 0, 0,
523                              revocation_reason_build_cb, reason );
524     if( rc ) {
525         log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
526         goto leave;
527     }
528
529     if(PGP2 || PGP6 || PGP7 || PGP8)
530       {
531         /* Use a minimal pk for PGPx mode, since PGP can't import bare
532            revocation certificates. */
533         rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
534         if(rc)
535           goto leave;
536       }
537     else
538       {
539         init_packet( &pkt );
540         pkt.pkttype = PKT_SIGNATURE;
541         pkt.pkt.signature = sig;
542
543         rc = build_packet( out, &pkt );
544         if( rc ) {
545           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
546           goto leave;
547         }
548       }
549
550     /* and issue a usage notice */
551     tty_printf(_("Revocation certificate created.\n\n"
552 "Please move it to a medium which you can hide away; if Mallory gets\n"
553 "access to this certificate he can use it to make your key unusable.\n"
554 "It is smart to print this certificate and store it away, just in case\n"
555 "your media become unreadable.  But have some caution:  The print system of\n"
556 "your machine might store the data and make it available to others!\n"));
557
558   leave:
559     if( sig )
560         free_seckey_enc( sig );
561     release_kbnode( keyblock );
562     release_kbnode( pub_keyblock );
563     keydb_release (kdbhd);
564     if( rc )
565         iobuf_cancel(out);
566     else
567         iobuf_close(out);
568     release_revocation_reason_info( reason );
569     return rc;
570 }
571
572
573
574 struct revocation_reason_info *
575 ask_revocation_reason( int key_rev, int cert_rev, int hint )
576 {
577     int code=-1;
578     char *description = NULL;
579     struct revocation_reason_info *reason;
580     const char *text_0 = _("No reason specified");
581     const char *text_1 = _("Key has been compromised");
582     const char *text_2 = _("Key is superseded");
583     const char *text_3 = _("Key is no longer used");
584     const char *text_4 = _("User ID is no longer valid");
585     const char *code_text = NULL;
586
587     do {
588         code=-1;
589         m_free(description);
590         description = NULL;
591
592         tty_printf(_("Please select the reason for the revocation:\n"));
593         tty_printf(    "  0 = %s\n", text_0 );
594         if( key_rev )
595             tty_printf("  1 = %s\n", text_1 );
596         if( key_rev )
597             tty_printf("  2 = %s\n", text_2 );
598         if( key_rev )
599             tty_printf("  3 = %s\n", text_3 );
600         if( cert_rev )
601             tty_printf("  4 = %s\n", text_4 );
602         tty_printf(    "  Q = %s\n", _("Cancel") );
603         if( hint )
604             tty_printf(_("(Probably you want to select %d here)\n"), hint );
605
606         while(code==-1) {
607             int n;
608             char *answer = cpr_get("ask_revocation_reason.code",
609                                                 _("Your decision? "));
610             trim_spaces( answer );
611             cpr_kill_prompt();
612             if( *answer == 'q' || *answer == 'Q')
613               return NULL; /* cancel */
614             if( hint && !*answer )
615                 n = hint;
616             else if(!digitp( answer ) )
617                 n = -1;
618             else
619                 n = atoi(answer);
620             m_free(answer);
621             if( n == 0 ) {
622                 code = 0x00; /* no particular reason */
623                 code_text = text_0;
624             }
625             else if( key_rev && n == 1 ) {
626                 code = 0x02; /* key has been compromised */
627                 code_text = text_1;
628             }
629             else if( key_rev && n == 2 ) {
630                 code = 0x01; /* key is superseded */
631                 code_text = text_2;
632             }
633             else if( key_rev && n == 3 ) {
634                 code = 0x03; /* key is no longer used */
635                 code_text = text_3;
636             }
637             else if( cert_rev && n == 4 ) {
638                 code = 0x20; /* uid is no longer valid */
639                 code_text = text_4;
640             }
641             else
642                 tty_printf(_("Invalid selection.\n"));
643         }
644
645         tty_printf(_("Enter an optional description; "
646                      "end it with an empty line:\n") );
647         for(;;) {
648             char *answer = cpr_get("ask_revocation_reason.text", "> " );
649             trim_trailing_ws( answer, strlen(answer) );
650             cpr_kill_prompt();
651             if( !*answer ) {
652                 m_free(answer);
653                 break;
654             }
655
656             {
657                 char *p = make_printable_string( answer, strlen(answer), 0 );
658                 m_free(answer);
659                 answer = p;
660             }
661
662             if( !description )
663                 description = m_strdup(answer);
664             else {
665                 char *p = m_alloc( strlen(description) + strlen(answer) + 2 );
666                 strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
667                 m_free(description);
668                 description = p;
669             }
670             m_free(answer);
671         }
672
673         tty_printf(_("Reason for revocation: %s\n"), code_text );
674         if( !description )
675             tty_printf(_("(No description given)\n") );
676         else
677             tty_printf("%s\n", description );
678
679     } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
680                                             _("Is this okay? (y/N) "))  );
681
682     reason = m_alloc( sizeof *reason );
683     reason->code = code;
684     reason->desc = description;
685     return reason;
686 }
687
688 void
689 release_revocation_reason_info( struct revocation_reason_info *reason )
690 {
691     if( reason ) {
692         m_free( reason->desc );
693         m_free( reason );
694     }
695 }