/[winpt]/trunk/MyGPGME/import.c
ViewVC logotype

Annotation of /trunk/MyGPGME/import.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Mon Apr 4 07:01:43 2005 UTC (19 years, 10 months ago) by twoaday
File MIME type: text/plain
File size: 15227 byte(s)
2005-03-22  Timo Schulz  <twoaday@freakmail.de>
                                                                                
        * editcard.c: Support new status-fd entries SC_OP_SUCCESS
        and SC_OP_FAILURE.
        * editkey.c (cmd_addrev_handler): Check if context != NULL.
        * import.c (import_command_handler): Wrong function signature.
        Noted by Kurt Fitzner.
        * types.h: Fixed encrypt_result_s. Noted by Kurt.
        * gpgme.h (gpgme_editkey_addrev_set): Changed return type.
        Kudos to Kurt.
        * key.c: Removed some unreachable code. By Kurt.
                                                                                


1 twoaday 2 /* import.c - import functions
2     * Copyright (C) 2000 Werner Koch (dd9jn)
3     * Copyright (C) 2001-2004 Timo Schulz
4     *
5     * This file is part of MyGPGME.
6     *
7     * MyGPGME 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     * MyGPGME 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 <stdio.h>
23     #include <stdlib.h>
24     #include <string.h>
25     #include <assert.h>
26     #include <ctype.h>
27    
28     #include "util.h"
29     #include "context.h"
30     #include "ops.h"
31     #include "key.h"
32    
33    
34     struct import_result_s {
35     gpgme_recipients_t keys;
36     int import_res[14];
37     int imported;
38     };
39    
40    
41     void
42     _gpgme_release_import_result( _import_result_t res )
43     {
44     if( res ) {
45     gpgme_recipients_release( res->keys );
46     res->keys = NULL;
47     safe_free( res );
48     }
49     } /* _gpgme_release_import_result */
50    
51    
52     gpgme_error_t
53     gpgme_get_import_status (gpgme_ctx_t ctx, int * import_res,
54     gpgme_recipients_t * r_keys )
55     {
56     gpgme_recipients_t k;
57     struct user_id_s * s;
58     int i;
59    
60     if (!ctx)
61     return mk_error( Invalid_Value );
62    
63     assert( ctx->result_type == RESULT_TYPE_IMPORT );
64     for (i = 0; i < 14; i++)
65     import_res[i] = ctx->result.import->import_res[i];
66     if (r_keys && ctx->result.import->keys) {
67     if (gpgme_recipients_new (&k))
68     return mk_error (Out_Of_Core);
69     for (s=ctx->result.import->keys->list; s; s=s->next)
70     gpgme_recipients_add_name (k, s->name);
71     *r_keys = k;
72     }
73     return 0;
74     } /* gpgme_get_import_status */
75    
76    
77    
78     static const char *
79 twoaday 7 import_command_handler (void *opaque, gpg_status_code_t code, const char * key)
80 twoaday 2 {
81 twoaday 7 gpgme_ctx_t ctx = opaque;
82 twoaday 2 struct user_id_s * r;
83    
84     if (code != STATUS_GET_BOOL)
85     return NULL;
86    
87     /* We can use the interactive mode to get a summary of the imported
88     keys. We always say YES in this case because the IMPORT_CHECK
89     contains the user-id and this might be useful */
90     if (!ctx->enc_to)
91     return "Y";
92    
93     for (r = ctx->enc_to->list; r; r = r->next) {
94     if (!strncmp (r->name, ctx->tmp_keyid+8, 8)) {
95     DEBUG1 ("interactive import `%s´: ok\n", ctx->tmp_keyid+8);
96     return "Y";
97     }
98     }
99     return "N";
100     } /* import_command_handler */
101    
102    
103     static void
104     import_status_handler (gpgme_ctx_t ctx, gpg_status_code_t code, char * args)
105     {
106     const char * s;
107    
108     if (ctx->out_of_core)
109     return;
110    
111     if( ctx->result_type == RESULT_TYPE_NONE ) {
112     assert ( !ctx->result.import );
113     ctx->result.import = calloc( 1, sizeof *ctx->result.import );
114     if( !ctx->result.import ) {
115     ctx->out_of_core = 1;
116     return;
117     }
118     ctx->result.import->imported = 0;
119     ctx->result_type = RESULT_TYPE_IMPORT;
120     }
121    
122     switch (code) {
123     case STATUS_NODATA:
124     ctx->result.import->imported = -1;
125     break;
126    
127     case STATUS_IMPORT_CHECK:
128     if (!ctx->result.import->keys)
129     gpgme_recipients_new (&ctx->result.import->keys);
130     s = args;
131     while (s && *s != ' ')
132     s++;
133     s++;
134     while (s && *s != ' ')
135     s++;
136     s++;
137     gpgme_recipients_add_name (ctx->result.import->keys, s);
138     strncpy (ctx->tmp_keyid, args, 16);
139     break;
140    
141     case STATUS_IMPORTED:
142     ctx->result.import->imported++;
143     break;
144    
145     case STATUS_IMPORT_RES:
146     /* IMPORT_RES <count> <no_user_id> <imported> <imported_rsa>
147     <unchanged> <n_uids> <n_subk> <n_sigs> <n_revoc>
148     <sec_read> <sec_imported> <sec_dups> <not_imported> */
149     ctx->result.import->imported++;
150     sscanf (args, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d",
151     &ctx->result.import->import_res[ 0],
152     &ctx->result.import->import_res[ 1],
153     &ctx->result.import->import_res[ 2],
154     &ctx->result.import->import_res[ 3],
155     &ctx->result.import->import_res[ 4],
156     &ctx->result.import->import_res[ 5],
157     &ctx->result.import->import_res[ 6],
158     &ctx->result.import->import_res[ 7],
159     &ctx->result.import->import_res[ 8],
160     &ctx->result.import->import_res[ 9],
161     &ctx->result.import->import_res[10],
162     &ctx->result.import->import_res[11],
163     &ctx->result.import->import_res[12],
164     &ctx->result.import->import_res[13]);
165     /* we add the RSA keys to have one sum. we don't need to differ
166     between RSA and other keys after the patent has been expired. */
167     ctx->result.import->import_res[2] += ctx->result.import->import_res[3];
168     break;
169     }
170     } /* import_status_handler */
171    
172    
173     static gpgme_error_t
174     import_start( gpgme_ctx_t ctx, gpgme_data_t keydata )
175     {
176     gpgme_error_t rc = 0;
177    
178     fail_on_pending_request( ctx );
179     ctx->pending = 1;
180    
181     /* create a process object */
182     _gpgme_gpg_release( &ctx->gpg );
183     rc = _gpgme_gpg_new( &ctx->gpg );
184     if( rc )
185     goto leave;
186    
187     if( ctx->interactive )
188     _gpgme_gpg_set_command_handler( ctx->gpg, import_command_handler, ctx );
189     if( ctx->use_logging )
190     _gpgme_gpg_set_logging_handler( ctx->gpg, ctx );
191     _gpgme_gpg_set_status_handler( ctx->gpg, import_status_handler, ctx );
192    
193     /* build the commandline */
194     if( ctx->force_opt )
195     _gpgme_gpg_add_arg( ctx->gpg, "--allow-non-selfsigned-uid" );
196     _gpgme_gpg_add_arg( ctx->gpg, "--allow-secret-key-import" );
197     if( ctx->interactive )
198     _gpgme_gpg_add_arg( ctx->gpg, "--interactive" );
199     _gpgme_gpg_add_arg ( ctx->gpg, "--import" );
200    
201     /* Check the supplied data */
202     if( gpgme_data_get_type( keydata ) == GPGME_DATA_TYPE_NONE ) {
203     rc = mk_error( No_Data );
204     goto leave;
205     }
206     _gpgme_data_set_mode( keydata, GPGME_DATA_MODE_OUT );
207     _gpgme_gpg_add_data( ctx->gpg, keydata, 0 );
208     rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
209    
210     leave:
211     if( rc ) {
212     ctx->pending = 0;
213     _gpgme_gpg_release ( &ctx->gpg );
214     }
215     return rc;
216     } /* import_start */
217    
218    
219     static gpgme_error_t
220     file_import_start( gpgme_ctx_t ctx, const char *input )
221     {
222     gpgme_error_t rc;
223    
224     if( !ctx )
225     return mk_error( Invalid_Value );
226    
227     fail_on_pending_request( ctx );
228     ctx->pending = 1;
229    
230     _gpgme_gpg_release( &ctx->gpg );
231     rc = _gpgme_gpg_new( &ctx->gpg );
232     if( rc )
233     return rc;
234    
235     if( ctx->interactive )
236     _gpgme_gpg_set_command_handler( ctx->gpg, import_command_handler, ctx );
237     _gpgme_gpg_set_status_handler( ctx->gpg, import_status_handler, ctx );
238     if( ctx->interactive )
239     _gpgme_gpg_add_arg( ctx->gpg, "--interactive" );
240     _gpgme_gpg_add_arg( ctx->gpg, "--yes" );
241     _gpgme_gpg_add_arg( ctx->gpg, "--allow-non-selfsigned-uid" );
242     _gpgme_gpg_add_arg( ctx->gpg, "--allow-secret-key-import" );
243     _gpgme_gpg_add_arg( ctx->gpg, "--import" );
244     _gpgme_gpg_add_arg( ctx->gpg, input );
245    
246     rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
247     if( rc ) {
248     ctx->pending = 0;
249     _gpgme_gpg_release( &ctx->gpg );
250     }
251    
252     return rc;
253     } /* file_import_start */
254    
255    
256     static gpgme_error_t
257     get_import_result( gpgme_ctx_t ctx )
258     {
259     gpgme_error_t err = 0;
260    
261     if( ctx->result_type != RESULT_TYPE_IMPORT )
262     err = mk_error( General_Error );
263     else if( ctx->out_of_core )
264     err = mk_error( Out_Of_Core );
265     else {
266     assert( ctx->result.import );
267     if( ctx->result.import->imported == -1 )
268     err = mk_error( No_Data );
269     else if( !ctx->result.import->imported )
270     err = mk_error( General_Error );
271     else if( gpgme_get_process_rc( ctx ) == 2
272     && ctx->result.import->import_res[GPGME_IMPSTAT_NSKEYS] ) {
273     /* GPG isssues a warning when the secret key is already
274     in the secret keyring. Due to the fact GPG can't merge
275     secret keys, the return code is incremented but this
276     is in fact no real error. */
277     err = 0;
278     }
279     else if( gpgme_get_process_rc( ctx ) )
280 twoaday 7 err = mk_error( Internal_GPG_Problem );
281 twoaday 2 }
282    
283     return err;
284     } /* get_import_result */
285    
286    
287     gpgme_error_t
288     gpgme_op_import( gpgme_ctx_t ctx, gpgme_recipients_t selkeys, gpgme_data_t keydata )
289     {
290     gpgme_error_t err;
291    
292     ctx->enc_to = selkeys;
293     err = import_start( ctx, keydata );
294     if( !err ) {
295     gpgme_wait( ctx, 1 );
296     ctx->pending = 0;
297     err = get_import_result( ctx );
298     }
299    
300     return err;
301     } /* gpgme_op_import */
302    
303    
304     gpgme_error_t
305     gpgme_op_file_import( gpgme_ctx_t ctx, gpgme_recipients_t selkeys, const char *input )
306     {
307     gpgme_error_t err;
308    
309     ctx->enc_to = selkeys;
310     err = file_import_start( ctx, input );
311     if( !err ) {
312     gpgme_wait( ctx, 1 );
313     ctx->pending = 0;
314     err = get_import_result( ctx );
315     }
316    
317     return err;
318     } /* gpgme_op_file_import */
319    
320    
321     gpgme_error_t
322     gpgme_op_clip_import (int ctrl, gpgme_recipients_t selkeys, int * import_res)
323     {
324     gpgme_error_t err = 0;
325     gpgme_ctx_t ctx = NULL;
326     gpgme_data_t keydata = NULL;
327    
328     err = gpgme_new (&ctx);
329     if (err)
330     return err;
331     if( ctrl & GPGME_CTRL_FORCEOPT )
332     gpgme_control( ctx, GPGME_CTRL_FORCEOPT, 1 );
333     err = gpgme_data_new_from_clipboard (&keydata);
334     if( !err )
335     err = gpgme_op_import( ctx, selkeys, keydata );
336     if( !err )
337     err = gpgme_get_import_status( ctx, import_res, NULL );
338    
339     gpgme_data_release( keydata );
340     gpgme_release( ctx );
341    
342     return err;
343     } /* gpgme_op_clip_import */
344    
345    
346     static gpgme_error_t
347     import_list_start( gpgme_ctx_t ctx, gpgme_data_t in, gpgme_data_t out )
348     {
349     gpgme_error_t rc;
350    
351     fail_on_pending_request( ctx );
352     ctx->pending = 1;
353    
354     _gpgme_gpg_release( &ctx->gpg );
355     rc = _gpgme_gpg_new( &ctx->gpg );
356     if( rc )
357     goto leave;
358    
359     /*_gpgme_gpg_add_arg( ctx->gpg, "--fast-list-mode" );*/
360     _gpgme_gpg_add_arg( ctx->gpg, "--fixed-list-mode" );
361     _gpgme_gpg_add_arg( ctx->gpg, "--with-colons" );
362    
363     if( gpgme_data_get_type( in ) == GPGME_DATA_TYPE_NONE ) {
364     rc = mk_error( No_Data );
365     goto leave;
366     }
367    
368     _gpgme_data_set_mode( in, GPGME_DATA_MODE_OUT );
369     _gpgme_data_set_mode( out, GPGME_DATA_MODE_IN );
370    
371     _gpgme_gpg_add_arg( ctx->gpg, "--output" );
372     _gpgme_gpg_add_arg( ctx->gpg, "-" );
373     _gpgme_gpg_add_data( ctx->gpg, out, 1 );
374     _gpgme_gpg_add_arg( ctx->gpg, "--" );
375     _gpgme_gpg_add_data( ctx->gpg, in, 0 );
376    
377     rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
378    
379     leave:
380     if( rc ) {
381     ctx->pending = 0;
382     _gpgme_gpg_release( &ctx->gpg );
383     }
384    
385     return rc;
386     } /* import_list_start */
387    
388    
389     gpgme_error_t
390     gpgme_op_import_list( gpgme_ctx_t ctx, gpgme_data_t in, gpgme_data_t out )
391     {
392     gpgme_error_t err;
393    
394     err = import_list_start( ctx, in, out );
395     if( !err ) {
396     gpgme_wait( ctx, 1 );
397     ctx->pending = 0;
398     if (gpgme_data_get_type (out) == GPGME_DATA_TYPE_NONE)
399     err = mk_error (General_Error);
400     else if (gpgme_get_process_rc (ctx))
401 twoaday 7 err = mk_error (Internal_GPG_Problem);
402 twoaday 2 }
403    
404     return err;
405     } /* gpgme_op_import_list */
406    
407    
408     static void
409     decode_userid( char * pend, gpgme_key_t c )
410     {
411     char * tmp;
412    
413     c->uids = calloc( 1, sizeof *c->uids + strlen( pend ) + 1 );
414     if( !c->uids )
415     return;
416     tmp = c->uids->name;
417     _gpgme_decode_c_string( pend, &tmp, strlen( pend ) + 1 );
418     c->uids->name[strlen( c->uids->name ) -3] = '\0';
419     } /* decode_userid */
420    
421    
422     static void
423     parse_colon_key( char *buf, gpgme_key_t c )
424     {
425     const char * s;
426     char *p, *pend;
427     int field = 0, rectype = 0;
428     struct subkey_s * subk;
429     enum {
430     KEY_none = 0,
431     KEY_primary = 1,
432     KEY_secondary = 2,
433     };
434    
435     if( !buf )
436     return; /* EOF */
437    
438     if( !strncmp( buf, "pub", 3 ) || !strncmp( buf, "sec", 3 ) ) {
439     rectype = KEY_primary;
440     if( *buf == 's' )
441     c->secret = 1;
442     }
443     else if( !strncmp( buf, "sub", 3 ) || !strncmp( buf, "ssb", 3 ) ) {
444     rectype = KEY_secondary;
445     if( !c->keys.next )
446     c->keys.next = subk = calloc( 1, sizeof *subk );
447     else
448     subk = c->keys.next;
449     }
450     else if( !strncmp( buf, "uid", 3 ) ) {
451     if( !c->uids ) {
452     const char * s = buf;
453     s += 3;
454     while( s && *s == ':' )
455     s++;
456     decode_userid( (char *)s, c );
457    
458     }
459     return;
460     }
461     else
462     return;
463    
464     for( p = buf; p; p = pend ) {
465     field++;
466     pend = strchr( p, ':' );
467     if( pend )
468     *pend++ = 0;
469    
470     switch( field ) {
471     case 1:
472     if( rectype != KEY_primary )
473     break;
474     for( s = pend; *s && !isdigit( *s ); s++ ) {
475     switch( *s ) {
476     case 'd': c->keys.flags.disabled = 1; break;
477     case 'e': c->keys.flags.expired = 1; break;
478     case 'r': c->keys.flags.revoked = 1; break;
479     }
480     }
481     break;
482    
483     case 2:
484     if( rectype == KEY_primary )
485     c->keys.key_len = atoi( pend );
486     else
487     subk->key_len = atoi( pend );
488     break;
489    
490     case 3:
491     if( rectype == KEY_primary )
492     c->keys.key_algo = atoi( pend );
493     else
494     subk->key_algo = atoi( pend );
495     break;
496    
497     case 4:
498     if( rectype == KEY_primary ) {
499     memcpy( c->keys.keyid, pend, 16 );
500     c->keys.keyid[16] = '\0';
501     }
502     else {
503     memcpy( subk->keyid, pend, 16 );
504     subk->keyid[16]= '\0';
505     }
506     break;
507    
508     case 5:
509     if( rectype == KEY_primary )
510     c->keys.timestamp = strtoul( pend, NULL, 10 );
511     else
512     subk->timestamp = strtoul( pend, NULL, 10 );
513     break;
514    
515     case 9:
516     if( rectype == KEY_primary && !c->uids && strlen( pend ) > 2 ) {
517     if( !strchr( pend, '[' ) && !strchr( pend, ']' ) )
518     decode_userid( pend, c );
519     }
520     break;
521     }
522     }
523     } /* parse_colon_key */
524    
525    
526     gpgme_error_t
527     gpgme_op_import_list_next( gpgme_data_t out, char **pending_line, gpgme_key_t *r_key )
528     {
529     gpgme_key_t key = NULL;
530     int in_cert, got_block = 0;
531     char buf[384];
532    
533     if( !r_key )
534     return mk_error( Invalid_Value );
535    
536     if( _gpgme_key_new( &key ) )
537     return mk_error( Out_Of_Core );
538    
539     if( *pending_line ) {
540     parse_colon_key( *pending_line, key );
541     safe_free( *pending_line );
542     *pending_line = NULL;
543     in_cert = 1;
544     }
545     else
546     in_cert = 0;
547    
548     while( gpgme_data_readline( out, buf, sizeof buf-1 ) ) {
549     if( !strncmp( buf, "pub", 3 )
550     || !strncmp( buf, "sec", 3 ) ) {
551     if( in_cert ) {
552     *pending_line = strdup( buf );
553     goto ready;
554     }
555     in_cert = 1, got_block = 1;
556     parse_colon_key( buf, key );
557     }
558     else if( in_cert ) {
559     parse_colon_key( buf, key );
560     got_block = 1;
561     }
562     }
563     ready:
564     *r_key = key;
565     if( got_block && _gpgme_data_eof( out ) )
566     return 0;
567     return _gpgme_data_eof( out ) ? mk_error( EOF ) : 0;
568     } /* gpgme_op_import_list_next */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26