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