See ChangeLog: Mon Jul 26 09:34:46 CEST 1999 Werner Koch
[gnupg.git] / g10 / export.c
1 /* export.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 "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 static int
75 do_export( STRLIST users, int secret, int onlyrfc )
76 {
77     IOBUF out = NULL;
78     int any, rc;
79     armor_filter_context_t afx;
80
81     memset( &afx, 0, sizeof afx);
82
83     rc = open_outfile( NULL, 0, &out );
84     if( rc )
85         return rc;
86
87     if( opt.armor ) {
88         afx.what = secret?5:1;
89         iobuf_push_filter( out, armor_filter, &afx );
90     }
91     rc = do_export_stream( out, users, secret, onlyrfc, &any );
92
93     if( rc || !any )
94         iobuf_cancel(out);
95     else
96         iobuf_close(out);
97     return rc;
98 }
99
100
101 static int
102 do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
103 {
104     int rc = 0;
105     compress_filter_context_t zfx;
106     PACKET pkt;
107     KBNODE keyblock = NULL;
108     KBNODE kbctx, node;
109     KBPOS kbpos;
110     STRLIST sl;
111     int all = !users;
112
113     *any = 0;
114     memset( &zfx, 0, sizeof zfx);
115     init_packet( &pkt );
116
117     if( opt.compress_keys && opt.compress )
118         iobuf_push_filter( out, compress_filter, &zfx );
119
120     if( all ) {
121         rc = enum_keyblocks( secret?5:0, &kbpos, &keyblock );
122         if( rc ) {
123             if( rc != -1 )
124                 log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
125             goto leave;
126         }
127         all = 2;
128     }
129
130     /* use the correct sequence. strlist_last,prev do work correctly with
131      * NULL pointers :-) */
132     for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
133         if( all ) { /* get the next user */
134             rc = enum_keyblocks( 1, &kbpos, &keyblock );
135             if( rc == -1 )  /* EOF */
136                 break;
137             if( rc ) {
138                 log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
139                 break;
140             }
141         }
142         else {
143             /* search the userid */
144             rc = secret? find_secret_keyblock_byname( &kbpos, sl->d )
145                        : find_keyblock_byname( &kbpos, sl->d );
146             if( rc ) {
147                 log_error(_("%s: user not found: %s\n"), sl->d, g10_errstr(rc));
148                 rc = 0;
149                 continue;
150             }
151             /* read the keyblock */
152             rc = read_keyblock( &kbpos, &keyblock );
153         }
154
155         if( rc ) {
156             log_error(_("certificate read problem: %s\n"), g10_errstr(rc));
157             goto leave;
158         }
159
160
161         /* do not export keys which are incompatible with rfc2440 */
162         if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
163             PKT_public_key *pk = node->pkt->pkt.public_key;
164             if( pk->version == 3 && pk->pubkey_algo > 3 ) {
165                 log_info(_("key %08lX: not a rfc2440 key - skipped\n"),
166                               (ulong)keyid_from_pk( pk, NULL) );
167                 continue;
168             }
169         }
170
171         /* and write it */
172         for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
173             /* don't export any comment packets but those in the
174              * secret keyring */
175             if( !secret && node->pkt->pkttype == PKT_COMMENT )
176                 continue;
177             /* do not export packets which are marked as not exportable */
178             if( node->pkt->pkttype == PKT_SIGNATURE ) {
179                 const char *p;
180                 p = parse_sig_subpkt2( node->pkt->pkt.signature,
181                                        SIGSUBPKT_EXPORTABLE, NULL );
182                 if( p && !*p )
183                     continue; /* not exportable */
184             }
185
186             if( (rc = build_packet( out, node->pkt )) ) {
187                 log_error("build_packet(%d) failed: %s\n",
188                             node->pkt->pkttype, g10_errstr(rc) );
189                 rc = G10ERR_WRITE_FILE;
190                 goto leave;
191             }
192         }
193         ++*any;
194     }
195     if( rc == -1 )
196         rc = 0;
197
198   leave:
199     if( all == 2 )
200         enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
201     release_kbnode( keyblock );
202     if( !*any )
203         log_info(_("WARNING: nothing exported\n"));
204     return rc;
205 }
206