* keyserver.c (parse_keyserver_uri, add_canonical_option): Always append
[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, STRLIST locusr )
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     SK_LIST sk_list=NULL;
215
216     if( opt.batch )
217       {
218         log_error(_("can't do this in batch mode\n"));
219         return G10ERR_GENERAL;
220       }
221
222     memset( &afx, 0, sizeof afx);
223
224     kdbhd = keydb_new (0);
225     classify_user_id (uname, &desc);
226     rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
227     if (rc) {
228         log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc));
229         goto leave;
230     }
231
232     rc = keydb_get_keyblock (kdbhd, &keyblock );
233     if( rc ) {
234         log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
235         goto leave;
236     }
237
238     /* To parse the revkeys */
239     merge_keys_and_selfsig(keyblock);
240
241     /* get the key from the keyblock */
242     node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
243     if( !node ) 
244       BUG ();
245
246     pk=node->pkt->pkt.public_key;
247
248     keyid_from_pk(pk,keyid);
249
250     if(locusr)
251       {
252         rc=build_sk_list(locusr,&sk_list,0,PUBKEY_USAGE_CERT);
253         if(rc)
254           goto leave;
255       }
256
257     /* Are we a designated revoker for this key? */
258
259     if(!pk->revkey && pk->numrevkeys)
260       BUG();
261
262     for(i=0;i<pk->numrevkeys;i++)
263       {
264         SK_LIST list;
265
266         if(sk)
267           free_secret_key(sk);
268
269         if(sk_list)
270           {
271             for(list=sk_list;list;list=list->next)
272               {
273                 byte fpr[MAX_FINGERPRINT_LEN];
274                 size_t fprlen;
275
276                 fingerprint_from_sk(list->sk,fpr,&fprlen);
277
278                 /* Don't get involved with keys that don't have 160
279                    bit fingerprints */
280                 if(fprlen!=20)
281                   continue;
282
283                 if(memcmp(fpr,pk->revkey[i].fpr,20)==0)
284                   break;
285               }
286
287             if(list)
288               sk=copy_secret_key(NULL,list->sk);
289             else
290               continue;
291           }
292         else
293           {
294             sk=xmalloc_secure_clear(sizeof(*sk));
295             rc=get_seckey_byfprint(sk,pk->revkey[i].fpr,MAX_FINGERPRINT_LEN);
296           }
297
298         /* We have the revocation key */
299         if(!rc)
300           {
301             PKT_signature *revkey = NULL;
302
303             any = 1;
304
305             print_pubkey_info (NULL, pk);
306             tty_printf ("\n");
307
308             tty_printf (_("To be revoked by:\n"));
309             print_seckey_info (sk);
310
311             if(pk->revkey[i].class&0x40)
312               tty_printf(_("(This is a sensitive revocation key)\n"));
313             tty_printf("\n");
314
315             if( !cpr_get_answer_is_yes("gen_desig_revoke.okay",
316          _("Create a designated revocation certificate for this key? (y/N) ")))
317               continue;
318
319             /* get the reason for the revocation (this is always v4) */
320             reason = ask_revocation_reason( 1, 0, 1 );
321             if( !reason )
322               continue;
323
324             rc = check_secret_key( sk, 0 );
325             if( rc )
326               continue;
327
328             if( !opt.armor )
329               tty_printf(_("ASCII armored output forced.\n"));
330
331             if( (rc = open_outfile( NULL, 0, &out )) )
332               goto leave;
333
334             afx.what = 1;
335             afx.hdrlines = "Comment: A designated revocation certificate"
336               " should follow\n";
337             iobuf_push_filter( out, armor_filter, &afx );
338
339             /* create it */
340             rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
341                                      0, 0, 0,
342                                      revocation_reason_build_cb, reason );
343             if( rc ) {
344               log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
345               goto leave;
346             }
347
348             /* Spit out a minimal pk as well, since otherwise there is
349                no way to know which key to attach this revocation to.
350                Also include the direct key signature that contains
351                this revocation key.  We're allowed to include
352                sensitive revocation keys along with a revocation, as
353                this may be the only time the recipient has seen it.
354                Note that this means that if we have multiple different
355                sensitive revocation keys in a given direct key
356                signature, we're going to include them all here.  This
357                is annoying, but the good outweighs the bad, since
358                without including this a sensitive revoker can't really
359                do their job.  People should not include multiple
360                sensitive revocation keys in one signature: 2440 says
361                "Note that it may be appropriate to isolate this
362                subpacket within a separate signature so that it is not
363                combined with other subpackets that need to be
364                exported." -dms */
365
366             while(!revkey)
367               {
368                 KBNODE signode;
369
370                 signode=find_next_kbnode(node,PKT_SIGNATURE);
371                 if(!signode)
372                   break;
373
374                 node=signode;
375
376                 if(keyid[0]==signode->pkt->pkt.signature->keyid[0] &&
377                    keyid[1]==signode->pkt->pkt.signature->keyid[1] &&
378                    IS_KEY_SIG(signode->pkt->pkt.signature))
379                   {
380                     int j;
381
382                     for(j=0;j<signode->pkt->pkt.signature->numrevkeys;j++)
383                       {
384                         if(pk->revkey[i].class==
385                            signode->pkt->pkt.signature->revkey[j]->class &&
386                            pk->revkey[i].algid==
387                            signode->pkt->pkt.signature->revkey[j]->algid &&
388                            memcmp(pk->revkey[i].fpr,
389                                   signode->pkt->pkt.signature->revkey[j]->fpr,
390                                   MAX_FINGERPRINT_LEN)==0)
391                           {
392                             revkey=signode->pkt->pkt.signature;
393                             break;
394                           }
395                       }
396                   }
397               }
398
399             if(!revkey)
400               BUG();
401
402             rc=export_minimal_pk(out,keyblock,sig,revkey);
403             if(rc)
404               goto leave;
405
406             /* and issue a usage notice */
407             tty_printf(_("Revocation certificate created.\n"));
408             break;
409           }
410       }
411
412     if(!any)
413       log_error(_("no revocation keys found for \"%s\"\n"),uname);
414
415   leave:
416     if( pk )
417         free_public_key( pk );
418     if( sk )
419         free_secret_key( sk );
420     if( sig )
421         free_seckey_enc( sig );
422
423     release_sk_list(sk_list);
424
425     if( rc )
426         iobuf_cancel(out);
427     else
428         iobuf_close(out);
429     release_revocation_reason_info( reason );
430     return rc;
431 }
432
433
434 /****************
435  * Generate a revocation certificate for UNAME
436  */
437 int
438 gen_revoke( const char *uname )
439 {
440     int rc = 0;
441     armor_filter_context_t afx;
442     PACKET pkt;
443     PKT_secret_key *sk; /* used as pointer into a kbnode */
444     PKT_public_key *pk = NULL;
445     PKT_signature *sig = NULL;
446     u32 sk_keyid[2];
447     IOBUF out = NULL;
448     KBNODE keyblock = NULL, pub_keyblock = NULL;
449     KBNODE node;
450     KEYDB_HANDLE kdbhd;
451     struct revocation_reason_info *reason = NULL;
452     KEYDB_SEARCH_DESC desc;
453
454     if( opt.batch )
455       {
456         log_error(_("can't do this in batch mode\n"));
457         return G10ERR_GENERAL;
458       }
459
460     memset( &afx, 0, sizeof afx);
461     init_packet( &pkt );
462
463     /* search the userid: 
464      * We don't want the whole getkey stuff here but the entire keyblock
465      */
466     kdbhd = keydb_new (1);
467     classify_user_id (uname, &desc);
468     rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID;
469     if (rc)
470       {
471         log_error (_("secret key \"%s\" not found: %s\n"),
472                    uname, g10_errstr (rc));
473         goto leave;
474       }
475
476     rc = keydb_get_keyblock (kdbhd, &keyblock );
477     if( rc ) {
478         log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
479         goto leave;
480     }
481
482     /* get the keyid from the keyblock */
483     node = find_kbnode( keyblock, PKT_SECRET_KEY );
484     if( !node ) 
485         BUG ();
486
487     /* fixme: should make a function out of this stuff,
488      * it's used all over the source */
489     sk = node->pkt->pkt.secret_key;
490     keyid_from_sk( sk, sk_keyid );
491     print_seckey_info (sk);
492
493     pk = xmalloc_clear( sizeof *pk );
494
495     /* FIXME: We should get the public key direct from the secret one */
496
497     pub_keyblock=get_pubkeyblock(sk_keyid);
498     if(!pub_keyblock)
499       {
500         log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
501         goto leave;
502       }
503
504     node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
505     if(!node)
506       BUG();
507
508     pk=node->pkt->pkt.public_key;
509
510     if( cmp_public_secret_key( pk, sk ) ) {
511         log_error(_("public key does not match secret key!\n") );
512         rc = G10ERR_GENERAL;
513         goto leave;
514     }
515
516     tty_printf("\n");
517     if( !cpr_get_answer_is_yes("gen_revoke.okay",
518                   _("Create a revocation certificate for this key? (y/N) ")) )
519       {
520         rc = 0;
521         goto leave;
522       }
523
524     if(sk->version>=4 || opt.force_v4_certs) {
525       /* get the reason for the revocation */
526       reason = ask_revocation_reason( 1, 0, 1 );
527       if( !reason ) { /* user decided to cancel */
528         rc = 0;
529         goto leave;
530       }
531     }
532
533     switch( is_secret_key_protected( sk ) ) {
534       case -1:
535         log_error(_("unknown protection algorithm\n"));
536         rc = G10ERR_PUBKEY_ALGO;
537         break;
538       case -3:
539         tty_printf (_("Secret parts of primary key are not available.\n"));
540         rc = G10ERR_NO_SECKEY;
541         break;
542       case 0:
543         tty_printf(_("NOTE: This key is not protected!\n"));
544         break;
545       default:
546         rc = check_secret_key( sk, 0 );
547         break;
548     }
549     if( rc )
550         goto leave;
551
552
553     if( !opt.armor )
554         tty_printf(_("ASCII armored output forced.\n"));
555
556     if( (rc = open_outfile( NULL, 0, &out )) )
557         goto leave;
558
559     afx.what = 1;
560     afx.hdrlines = "Comment: A revocation certificate should follow\n";
561     iobuf_push_filter( out, armor_filter, &afx );
562
563     /* create it */
564     rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
565                              opt.force_v4_certs?4:0, 0, 0,
566                              revocation_reason_build_cb, reason );
567     if( rc ) {
568         log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
569         goto leave;
570     }
571
572     if(PGP2 || PGP6 || PGP7 || PGP8)
573       {
574         /* Use a minimal pk for PGPx mode, since PGP can't import bare
575            revocation certificates. */
576         rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
577         if(rc)
578           goto leave;
579       }
580     else
581       {
582         init_packet( &pkt );
583         pkt.pkttype = PKT_SIGNATURE;
584         pkt.pkt.signature = sig;
585
586         rc = build_packet( out, &pkt );
587         if( rc ) {
588           log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
589           goto leave;
590         }
591       }
592
593     /* and issue a usage notice */
594     tty_printf(_("Revocation certificate created.\n\n"
595 "Please move it to a medium which you can hide away; if Mallory gets\n"
596 "access to this certificate he can use it to make your key unusable.\n"
597 "It is smart to print this certificate and store it away, just in case\n"
598 "your media become unreadable.  But have some caution:  The print system of\n"
599 "your machine might store the data and make it available to others!\n"));
600
601   leave:
602     if( sig )
603         free_seckey_enc( sig );
604     release_kbnode( keyblock );
605     release_kbnode( pub_keyblock );
606     keydb_release (kdbhd);
607     if( rc )
608         iobuf_cancel(out);
609     else
610         iobuf_close(out);
611     release_revocation_reason_info( reason );
612     return rc;
613 }
614
615
616
617 struct revocation_reason_info *
618 ask_revocation_reason( int key_rev, int cert_rev, int hint )
619 {
620     int code=-1;
621     char *description = NULL;
622     struct revocation_reason_info *reason;
623     const char *text_0 = _("No reason specified");
624     const char *text_1 = _("Key has been compromised");
625     const char *text_2 = _("Key is superseded");
626     const char *text_3 = _("Key is no longer used");
627     const char *text_4 = _("User ID is no longer valid");
628     const char *code_text = NULL;
629
630     do {
631         code=-1;
632         xfree(description);
633         description = NULL;
634
635         tty_printf(_("Please select the reason for the revocation:\n"));
636         tty_printf(    "  0 = %s\n", text_0 );
637         if( key_rev )
638             tty_printf("  1 = %s\n", text_1 );
639         if( key_rev )
640             tty_printf("  2 = %s\n", text_2 );
641         if( key_rev )
642             tty_printf("  3 = %s\n", text_3 );
643         if( cert_rev )
644             tty_printf("  4 = %s\n", text_4 );
645         tty_printf(    "  Q = %s\n", _("Cancel") );
646         if( hint )
647             tty_printf(_("(Probably you want to select %d here)\n"), hint );
648
649         while(code==-1) {
650             int n;
651             char *answer = cpr_get("ask_revocation_reason.code",
652                                                 _("Your decision? "));
653             trim_spaces( answer );
654             cpr_kill_prompt();
655             if( *answer == 'q' || *answer == 'Q')
656               return NULL; /* cancel */
657             if( hint && !*answer )
658                 n = hint;
659             else if(!digitp( answer ) )
660                 n = -1;
661             else
662                 n = atoi(answer);
663             xfree(answer);
664             if( n == 0 ) {
665                 code = 0x00; /* no particular reason */
666                 code_text = text_0;
667             }
668             else if( key_rev && n == 1 ) {
669                 code = 0x02; /* key has been compromised */
670                 code_text = text_1;
671             }
672             else if( key_rev && n == 2 ) {
673                 code = 0x01; /* key is superseded */
674                 code_text = text_2;
675             }
676             else if( key_rev && n == 3 ) {
677                 code = 0x03; /* key is no longer used */
678                 code_text = text_3;
679             }
680             else if( cert_rev && n == 4 ) {
681                 code = 0x20; /* uid is no longer valid */
682                 code_text = text_4;
683             }
684             else
685                 tty_printf(_("Invalid selection.\n"));
686         }
687
688         tty_printf(_("Enter an optional description; "
689                      "end it with an empty line:\n") );
690         for(;;) {
691             char *answer = cpr_get("ask_revocation_reason.text", "> " );
692             trim_trailing_ws( answer, strlen(answer) );
693             cpr_kill_prompt();
694             if( !*answer ) {
695                 xfree(answer);
696                 break;
697             }
698
699             {
700                 char *p = make_printable_string( answer, strlen(answer), 0 );
701                 xfree(answer);
702                 answer = p;
703             }
704
705             if( !description )
706                 description = xstrdup(answer);
707             else {
708                 char *p = xmalloc( strlen(description) + strlen(answer) + 2 );
709                 strcpy(stpcpy(stpcpy( p, description),"\n"),answer);
710                 xfree(description);
711                 description = p;
712             }
713             xfree(answer);
714         }
715
716         tty_printf(_("Reason for revocation: %s\n"), code_text );
717         if( !description )
718             tty_printf(_("(No description given)\n") );
719         else
720             tty_printf("%s\n", description );
721
722     } while( !cpr_get_answer_is_yes("ask_revocation_reason.okay",
723                                             _("Is this okay? (y/N) "))  );
724
725     reason = xmalloc( sizeof *reason );
726     reason->code = code;
727     reason->desc = description;
728     return reason;
729 }
730
731 void
732 release_revocation_reason_info( struct revocation_reason_info *reason )
733 {
734     if( reason ) {
735         xfree( reason->desc );
736         xfree( reason );
737     }
738 }