Added more doc entries and prepared for 0.2.3
[gpgme.git] / gpgme / genkey.c
1 /* genkey.c -  key generation
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME 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  * GPGME 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32 static void
33 genkey_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
34 {
35     if ( code == STATUS_PROGRESS && *args ) {
36         if (ctx->progress_cb) {
37             char *p;
38             int type=0, current=0, total=0;
39             
40             if ( (p = strchr (args, ' ')) ) {
41                 *p++ = 0;
42                 if (*p) {
43                     type = *(byte*)p;
44                     if ( (p = strchr (p+1, ' ')) ) {
45                         *p++ = 0;
46                         if (*p) {
47                             current = atoi (p);
48                             if ( (p = strchr (p+1, ' ')) ) {
49                                 *p++ = 0;
50                                 total = atoi (p);
51                             }
52                         }
53                     }
54                 }
55             }           
56             if ( type != 'X' )
57                 ctx->progress_cb ( ctx->progress_cb_value, args, type,
58                                    current, total );
59         }
60         return;
61     }
62
63     DEBUG2 ("genkey_status: code=%d args=`%s'\n", code, args );
64     /* FIXME: Need to do more */
65 }
66
67
68 /**
69  * gpgme_op_genkey:
70  * @c: the context
71  * @parms: XML string with the key parameters
72  * @pubkey: Returns the public key
73  * @seckey: Returns the secret key
74  * 
75  * Generate a new key and store the key in the default keyrings if
76  * both @pubkey and @seckey are NULL.  If @pubkey and @seckey are
77  * given, the newly created key will be returned in these data
78  * objects.  This function just starts the gheneration and does not
79  * wait for completion.
80  *
81  * Here is an example on how @parms should be formatted; for deatils
82  * see the file doc/DETAILS from the GnuPG distribution.
83  *
84  * <literal>
85  * <![CDATA[
86  * <GnupgKeyParms format="internal">
87  * Key-Type: DSA
88  * Key-Length: 1024
89  * Subkey-Type: ELG-E
90  * Subkey-Length: 1024
91  * Name-Real: Joe Tester
92  * Name-Comment: with stupid passphrase
93  * Name-Email: joe@foo.bar
94  * Expire-Date: 0
95  * Passphrase: abc
96  * </GnupgKeyParms>
97  * ]]>
98  * </literal> 
99  *
100  * Strings should be given in UTF-8 encoding.  The format we support
101  * for now is only "internal".  The content of the
102  * &lt;GnupgKeyParms&gt; container is passed verbatim to GnuPG.
103  * Control statements are not allowed.
104  * 
105  * Return value: 0 for success or an error code
106  **/
107
108 GpgmeError
109 gpgme_op_genkey_start ( GpgmeCtx c, const char *parms,
110                         GpgmeData pubkey, GpgmeData seckey )
111 {
112     int rc = 0;
113     int i;
114     const char *s, *s2, *sx;
115
116     fail_on_pending_request( c );
117     c->pending = 1;
118
119     gpgme_data_release (c->help_data_1); c->help_data_1 = NULL;
120
121     /* create a process object */
122     _gpgme_gpg_release (c->gpg); c->gpg = NULL;
123     rc = _gpgme_gpg_new ( &c->gpg );
124     if (rc)
125         goto leave;
126
127     /* We need a special mechanism to get the fd of a pipe here, so
128      * that we can use this for the %pubring and %secring parameters.
129      * We don't have this yet, so we implement only the adding to the
130      * standard keyrings */
131     if ( pubkey || seckey ) {
132         rc = mk_error (Not_Implemented);
133         goto leave;
134     }
135
136     _gpgme_gpg_set_status_handler ( c->gpg, genkey_status_handler, c );
137
138     /* build the commandline */
139     _gpgme_gpg_add_arg ( c->gpg, "--gen-key" );
140     if ( c->use_armor )
141         _gpgme_gpg_add_arg ( c->gpg, "--armor" );
142     for ( i=0; i < c->verbosity; i++ )
143         _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
144
145     if ( !pubkey && !seckey )
146         ; /* okay: Add key to the keyrings */
147     else if ( !pubkey
148               || gpgme_data_get_type (pubkey) != GPGME_DATA_TYPE_NONE ) {
149         rc = mk_error (Invalid_Value);
150         goto leave;
151     }
152     else if ( !seckey
153               || gpgme_data_get_type (seckey) != GPGME_DATA_TYPE_NONE ) {
154         rc = mk_error (Invalid_Value);
155         goto leave;
156     }
157     
158     if ( pubkey ) {
159         _gpgme_data_set_mode (pubkey, GPGME_DATA_MODE_IN );
160         _gpgme_data_set_mode (seckey, GPGME_DATA_MODE_IN );
161         /* need some more things here */
162     }
163
164
165     if ( (parms = strstr (parms, "<GnupgKeyParms ")) 
166          && (s = strchr (parms, '>'))
167          && (sx = strstr (parms, "format=\"internal\""))
168          && sx < s
169          && (s2 = strstr (s+1, "</GnupgKeyParms>")) ) {
170         /* fixme: check that there are no control statements inside */
171         rc = gpgme_data_new_from_mem ( &c->help_data_1, s+1, s2-s-1, 1 );
172     }
173     else 
174         rc = mk_error (Invalid_Value);
175
176     if (rc )
177         goto leave;
178     
179     _gpgme_data_set_mode (c->help_data_1, GPGME_DATA_MODE_OUT );
180     _gpgme_gpg_add_data (c->gpg, c->help_data_1, 0);
181
182     rc = _gpgme_gpg_spawn ( c->gpg, c );
183     
184  leave:
185     if (rc) {
186         c->pending = 0; 
187         _gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
188     }
189     return rc;
190 }
191
192
193
194 /**
195  * gpgme_op_genkey:
196  * @c: the context
197  * @parms: XML string with the key parameters
198  * @pubkey: Returns the public key
199  * @seckey: Returns the secret key
200  * 
201  * Generate a new key and store the key in the default keyrings if both
202  * @pubkey and @seckey are NULL.  If @pubkey and @seckey are given, the newly
203  * created key will be returned in these data objects.
204  * See gpgme_op_genkey_start() for a description of @parms.
205  * 
206  * Return value: 0 for success or an error code
207  **/
208 GpgmeError
209 gpgme_op_genkey( GpgmeCtx c, const char *parms,
210                  GpgmeData pubkey, GpgmeData seckey )
211 {
212     int rc = gpgme_op_genkey_start ( c, parms, pubkey, seckey );
213     if ( !rc ) {
214         gpgme_wait (c, 1);
215         c->pending = 0;
216     }
217     return rc;
218 }
219
220
221
222
223