Converted all m_free to xfree etc.
[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 0:
501         tty_printf(_("NOTE: This key is not protected!\n"));
502         break;
503       default:
504         rc = check_secret_key( sk, 0 );
505         break;
506     }
507     if( rc )
508         goto leave;
509
510
511     if( !opt.armor )
512         tty_printf(_("ASCII armored output forced.\n"));
513
514     if( (rc = open_outfile( NULL, 0, &out )) )
515         goto leave;
516
517     afx.what = 1;
518     afx.hdrlines = "Comment: A revocation certificate should follow\n";
519     iobuf_push_filter( out, armor_filter, &afx );
520
521     /* create it */
522     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
523                              opt.force_v4_certs?4:0, 0, 0,
524                              revocation_reason_build_cb, reason );
525     if( rc ) {
526         log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
527         goto leave;
528     }
529
530     if(PGP2 || PGP6 || PGP7 || PGP8)
531       {
532         /* Use a minimal pk for PGPx mode, since PGP can't import bare
533            revocation certificates. */
534         rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
535         if(rc)
536           goto leave;
537       }
538     else
539       {
540         init_packet( &pkt );
541         pkt.pkttype = PKT_SIGNATURE;
542         pkt.pkt.signature = sig;
543
544         rc = build_packet( out, &pkt );
545         if( rc ) {
546           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
547           goto leave;
548         }
549       }
550
551     /* and issue a usage notice */
552     tty_printf(_("Revocation certificate created.\n\n"
553 "Please move it to a medium which you can hide away; if Mallory gets\n"
554 "access to this certificate he can use it to make your key unusable.\n"
555 "It is smart to print this certificate and store it away, just in case\n"
556 "your media become unreadable.  But have some caution:  The print system of\n"
557 "your machine might store the data and make it available to others!\n"));
558
559   leave:
560     if( sig )
561         free_seckey_enc( sig );
562     release_kbnode( keyblock );
563     release_kbnode( pub_keyblock );
564     keydb_release (kdbhd);
565     if( rc )
566         iobuf_cancel(out);
567     else
568         iobuf_close(out);
569     release_revocation_reason_info( reason );
570     return rc;
571 }
572
573
574
575 struct revocation_reason_info *
576 ask_revocation_reason( int key_rev, int cert_rev, int hint )
577 {
578     int code=-1;
579     char *description = NULL;
580     struct revocation_reason_info *reason;
581     const char *text_0 = _("No reason specified");
582     const char *text_1 = _("Key has been compromised");
583     const char *text_2 = _("Key is superseded");
584     const char *text_3 = _("Key is no longer used");
585     const char *text_4 = _("User ID is no longer valid");
586     const char *code_text = NULL;
587
588     do {
589         code=-1;
590         xfree(description);
591         description = NULL;
592
593         tty_printf(_("Please select the reason for the revocation:\n"));
594         tty_printf(    "  0 = %s\n", text_0 );
595         if( key_rev )
596             tty_printf("  1 = %s\n", text_1 );
597         if( key_rev )
598             tty_printf("  2 = %s\n", text_2 );
599         if( key_rev )
600             tty_printf("  3 = %s\n", text_3 );
601         if( cert_rev )
602             tty_printf("  4 = %s\n", text_4 );
603         tty_printf(    "  Q = %s\n", _("Cancel") );
604         if( hint )
605             tty_printf(_("(Probably you want to select %d here)\n"), hint );
606
607         while(code==-1) {
608             int n;
609             char *answer = cpr_get("ask_revocation_reason.code",
610                                                 _("Your decision? "));
611             trim_spaces( answer );
612             cpr_kill_prompt();
613             if( *answer == 'q' || *answer == 'Q')
614               return NULL; /* cancel */
615             if( hint && !*answer )
616                 n = hint;
617             else if(!digitp( answer ) )
618                 n = -1;
619             else
620                 n = atoi(answer);
621             xfree(answer);
622             if( n == 0 ) {
623                 code = 0x00; /* no particular reason */
624                 code_text = text_0;
625             }
626             else if( key_rev && n == 1 ) {
627                 code = 0x02; /* key has been compromised */
628                 code_text = text_1;
629             }
630             else if( key_rev && n == 2 ) {
631                 code = 0x01; /* key is superseded */
632                 code_text = text_2;
633             }
634             else if( key_rev && n == 3 ) {
635                 code = 0x03; /* key is no longer used */
636                 code_text = text_3;
637             }
638             else if( cert_rev && n == 4 ) {
639                 code = 0x20; /* uid is no longer valid */
640                 code_text = text_4;
641             }
642             else
643                 tty_printf(_("Invalid selection.\n"));
644         }
645
646         tty_printf(_("Enter an optional description; "
647                      "end it with an empty line:\n") );
648         for(;;) {
649             char *answer = cpr_get("ask_revocation_reason.text", "> " );
650             trim_trailing_ws( answer, strlen(answer) );
651             cpr_kill_prompt();
652             if( !*answer ) {
653                 xfree(answer);
654                 break;
655             }
656
657             {
658                 char *p = make_printable_string( answer, strlen(answer), 0 );
659                 xfree(answer);
660                 answer = p;
661             }
662
663             if( !description )
664                 description = xstrdup(answer);
665             else {
666                 char *p = xmalloc( strlen(description) + strlen(answer) + 2 );
667                 strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
668                 xfree(description);
669                 description = p;
670             }
671             xfree(answer);
672         }
673
674         tty_printf(_("Reason for revocation: %s\n"), code_text );
675         if( !description )
676             tty_printf(_("(No description given)\n") );
677         else
678             tty_printf("%s\n", description );
679
680     } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
681                                             _("Is this okay? (y/N) "))  );
682
683     reason = xmalloc( sizeof *reason );
684     reason->code = code;
685     reason->desc = description;
686     return reason;
687 }
688
689 void
690 release_revocation_reason_info( struct revocation_reason_info *reason )
691 {
692     if( reason ) {
693         xfree( reason->desc );
694         xfree( reason );
695     }
696 }