86d465cc0000273f50afe38ba39168337dde810f
[gnupg.git] / g10 / revoke.c
1 /* revoke.c
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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
28 #include "options.h"
29 #include "packet.h"
30 #include "errors.h"
31 #include "keydb.h"
32 #include "memory.h"
33 #include "util.h"
34 #include "main.h"
35 #include "ttyio.h"
36
37
38 /****************
39  * Generate a revocation certificate for UNAME
40  */
41 int
42 gen_revoke( const char *uname )
43 {
44     int rc = 0;
45     armor_filter_context_t afx;
46     compress_filter_context_t zfx;
47     PACKET pkt;
48     PKT_secret_cert *skc; /* used as pointer into a kbnode */
49     PKT_public_cert *pkc = NULL;
50     PKT_signature *sig = NULL;
51     u32 skc_keyid[2];
52     IOBUF out = NULL;
53     KBNODE keyblock = NULL;
54     KBNODE node;
55     KBPOS kbpos;
56     char *answer;
57     int yes;
58
59     if( opt.batch ) {
60         log_error("sorry, can't do this in batch mode\n");
61         return G10ERR_GENERAL;
62     }
63
64
65     memset( &afx, 0, sizeof afx);
66     memset( &zfx, 0, sizeof zfx);
67     init_packet( &pkt );
68
69
70     /* search the userid */
71     rc = find_secret_keyblock_byname( &kbpos, uname );
72     if( rc ) {
73         log_error("secret key for user '%s' not found\n", uname );
74         goto leave;
75     }
76
77     /* read the keyblock */
78     rc = read_keyblock( &kbpos, &keyblock );
79     if( rc ) {
80         log_error("error reading the certificate: %s\n", g10_errstr(rc) );
81         goto leave;
82     }
83
84     /* get the keyid from the keyblock */
85     node = find_kbnode( keyblock, PKT_SECRET_CERT );
86     if( !node ) { /* maybe better to use log_bug ? */
87         log_error("Oops; secret key not found anymore!\n");
88         rc = G10ERR_GENERAL;
89         goto leave;
90     }
91
92     /* FIXME: should make a function out of this stuff,
93      * it's used all over the source */
94     skc = node->pkt->pkt.secret_cert;
95     keyid_from_skc( skc, skc_keyid );
96     tty_printf("\nsec  %4u%c/%08lX %s   ",
97               nbits_from_skc( skc ),
98               pubkey_letter( skc->pubkey_algo ),
99               skc_keyid[1], datestr_from_skc(skc) );
100     {
101         size_t n;
102         char *p = get_user_id( skc_keyid, &n );
103         tty_print_string( p, n );
104         m_free(p);
105         tty_printf("\n");
106     }
107     /* the the pkc */
108     pkc = m_alloc_clear( sizeof *pkc );
109     rc = get_pubkey( pkc, skc_keyid );
110     if( rc ) {
111         log_error("no corresponding public key: %s\n", g10_errstr(rc) );
112         goto leave;
113     }
114     if( cmp_public_secret_cert( pkc, skc ) ) {
115         log_error("public key does not match secret key!\n" );
116         rc = G10ERR_GENERAL;
117         goto leave;
118     }
119
120     tty_printf("\n");
121     answer = tty_get("Create a revocation certificate for this key? ");
122     tty_kill_prompt();
123     yes = answer_is_yes(answer);
124     m_free(answer);
125     if( !yes ) {
126         rc = 0;
127         goto leave;
128     }
129
130     switch( is_secret_key_protected( skc ) ) {
131       case -1:
132         log_error("unknown protection algorithm\n");
133         rc = G10ERR_PUBKEY_ALGO;
134         break;
135       case 0:
136         tty_printf("Warning: This key is not protected!\n");
137         break;
138       default:
139         rc = check_secret_key( skc );
140         break;
141     }
142     if( rc )
143         goto leave;
144
145
146     if( !opt.armor )
147         tty_printf("ASCII armored output forced.\n");
148
149     if( !(out = open_outfile( NULL, 0 )) ) {
150         rc = G10ERR_CREATE_FILE;
151         goto leave;
152     }
153
154     afx.what = 1;
155     afx.hdrlines = "Comment: A revocation certificate should follow\n";
156     iobuf_push_filter( out, armor_filter, &afx );
157     if( opt.compress )
158         iobuf_push_filter( out, compress_filter, &zfx );
159
160
161     /* create it */
162     rc = make_keysig_packet( &sig, pkc, NULL, skc, 0x20, DIGEST_ALGO_RMD160);
163     if( rc ) {
164         log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
165         goto leave;
166     }
167     init_packet( &pkt );
168     pkt.pkttype = PKT_SIGNATURE;
169     pkt.pkt.signature = sig;
170
171     rc = build_packet( out, &pkt );
172     if( rc ) {
173         log_error("build_packet failed: %s\n", g10_errstr(rc) );
174         goto leave;
175     }
176
177     /* and issue a usage notice */
178     tty_printf("Revocation certificate created.\n\n"
179 "Please move it to a media, which you can hide away; if Mallory gets\n"
180 "access to this certificate he can use it to make your key unusable.\n"
181 "It is clever to print this certificate and store it away, just in the case\n"
182 "your media gets unreadable.  But have some caution:  The printer system of\n"
183 "your machine might store the data and make it availabe to others!\n");
184
185
186
187   leave:
188     if( pkc )
189         free_public_cert( pkc );
190     if( sig )
191         free_seckey_enc( sig );
192     release_kbnode( keyblock );
193     if( rc )
194         iobuf_cancel(out);
195     else
196         iobuf_close(out);
197     return rc;
198 }
199
200