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

Annotation of /trunk/MyGPGME/import.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Mon Jan 31 11:02:21 2005 UTC (20 years, 1 month ago) by twoaday
File MIME type: text/plain
File size: 15197 byte(s)
WinPT initial checkin.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26