See ChangeLog: Wed Oct 4 13:16:18 CEST 2000 Werner Koch
[gnupg.git] / g10 / export.c
1 /* export.c
2  *      Copyright (C) 1998, 1999, 2000 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 <gcrypt.h>
29 #include "options.h"
30 #include "packet.h"
31 #include "errors.h"
32 #include "keydb.h"
33 #include "util.h"
34 #include "main.h"
35 #include "i18n.h"
36
37 static int do_export( STRLIST users, int secret, int onlyrfc );
38 static int do_export_stream( IOBUF out, STRLIST users,
39                              int secret, int onlyrfc, int *any );
40
41 /****************
42  * Export the public keys (to standard out or --output).
43  * Depending on opt.armor the output is armored.
44  * If onlyrfc is True only RFC24404 compatible keys are exported.
45  * If USERS is NULL, the complete ring will be exported.
46  */
47 int
48 export_pubkeys( STRLIST users, int onlyrfc )
49 {
50     return do_export( users, 0, onlyrfc );
51 }
52
53 /****************
54  * Export to an already opened stream; return -1 if no keys have
55  * been exported
56  */
57 int
58 export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc )
59 {
60     int any, rc;
61
62     rc = do_export_stream( out, users, 0, onlyrfc, &any );
63     if( !rc && !any )
64         rc = -1;
65     return rc;
66 }
67
68 int
69 export_seckeys( STRLIST users )
70 {
71     return do_export( users, 1, 0 );
72 }
73
74 int
75 export_secsubkeys( STRLIST users )
76 {
77     return do_export( users, 2, 0 );
78 }
79
80 static int
81 do_export( STRLIST users, int secret, int onlyrfc )
82 {
83     IOBUF out = NULL;
84     int any, rc;
85     armor_filter_context_t afx;
86
87     memset( &afx, 0, sizeof afx);
88
89     rc = open_outfile( NULL, 0, &out );
90     if( rc )
91         return rc;
92
93     if( opt.armor ) {
94         afx.what = secret?5:1;
95         iobuf_push_filter( out, armor_filter, &afx );
96     }
97     rc = do_export_stream( out, users, secret, onlyrfc, &any );
98
99     if( rc || !any )
100         iobuf_cancel(out);
101     else
102         iobuf_close(out);
103     return rc;
104 }
105
106
107 static int
108 do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
109 {
110     int rc = 0;
111     compress_filter_context_t zfx;
112     PACKET pkt;
113     KBNODE keyblock = NULL;
114     KBNODE kbctx, node;
115     KBPOS kbpos;
116     STRLIST sl;
117     int all = !users;
118
119     *any = 0;
120     memset( &zfx, 0, sizeof zfx);
121     init_packet( &pkt );
122
123     if( opt.compress_keys && opt.compress )
124         iobuf_push_filter( out, compress_filter, &zfx );
125
126     if( all ) {
127         rc = enum_keyblocks( secret?5:0, &kbpos, &keyblock );
128         if( rc ) {
129             if( rc != -1 )
130                 log_error("enum_keyblocks(open) failed: %s\n", gpg_errstr(rc) );
131             goto leave;
132         }
133         all = 2;
134     }
135
136     /* use the correct sequence. strlist_last,prev do work correctly with
137      * NULL pointers :-) */
138     for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
139         if( all ) { /* get the next user */
140             rc = enum_keyblocks( 1, &kbpos, &keyblock );
141             if( rc == -1 )  /* EOF */
142                 break;
143             if( rc ) {
144                 log_error("enum_keyblocks(read) failed: %s\n", gpg_errstr(rc));
145                 break;
146             }
147         }
148         else {
149             /* search the userid */
150             rc = secret? find_secret_keyblock_byname( &kbpos, sl->d )
151                        : find_keyblock_byname( &kbpos, sl->d );
152             if( rc ) {
153                 log_error(_("%s: user not found: %s\n"), sl->d, gpg_errstr(rc));
154                 rc = 0;
155                 continue;
156             }
157             /* read the keyblock */
158             rc = read_keyblock( &kbpos, &keyblock );
159         }
160
161         if( rc ) {
162             log_error(_("certificate read problem: %s\n"), gpg_errstr(rc));
163             goto leave;
164         }
165       
166
167         /* do not export keys which are incompatible with rfc2440 */
168         if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
169             PKT_public_key *pk = node->pkt->pkt.public_key;
170             if( pk->version == 3 && pk->pubkey_algo > 3 ) {
171                 log_info(_("key %08lX: not a rfc2440 key - skipped\n"),
172                               (ulong)keyid_from_pk( pk, NULL) );
173                 continue;
174             }
175         }
176
177         /* we can't apply GNU mode 1001 on an unprotected key */
178         if( secret == 2
179             && (node = find_kbnode( keyblock, PKT_SECRET_KEY ))
180             && !node->pkt->pkt.secret_key->is_protected )
181         {
182             log_info(_("key %08lX: not protected - skipped\n"),
183                   (ulong)keyid_from_sk( node->pkt->pkt.secret_key, NULL) );
184             continue;
185         }
186
187         /* and write it */
188         for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
189             /* don't export any comment packets but those in the
190              * secret keyring */
191             if( !secret && node->pkt->pkttype == PKT_COMMENT )
192                 continue;
193             /* do not export packets which are marked as not exportable */
194             if( node->pkt->pkttype == PKT_SIGNATURE ) {
195                 const char *p;
196                 p = parse_sig_subpkt2( node->pkt->pkt.signature,
197                                        SIGSUBPKT_EXPORTABLE, NULL );
198                 if( p && !*p )
199                     continue; /* not exportable */
200             }
201
202             if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) {
203                 /* we don't want to export the secret parts of the
204                  * primary key, this is done by using GNU protection mode 1001
205                  */
206                 int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
207                 node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
208                 rc = build_packet( out, node->pkt );
209                 node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
210             }
211             else {
212                 rc = build_packet( out, node->pkt );
213             }
214
215             if( rc ) {
216                 log_error("build_packet(%d) failed: %s\n",
217                             node->pkt->pkttype, gpg_errstr(rc) );
218                 rc = GPGERR_WRITE_FILE;
219                 goto leave;
220             }
221         }
222         ++*any;
223     }
224     if( rc == -1 )
225         rc = 0;
226
227   leave:
228     if( all == 2 )
229         enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
230     release_kbnode( keyblock );
231     if( !*any )
232         log_info(_("WARNING: nothing exported\n"));
233     return rc;
234 }
235