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