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

Annotation of /trunk/MyGPGME/import.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Wed Aug 10 11:33:35 2005 UTC (19 years, 6 months ago) by twoaday
File MIME type: text/plain
File size: 15676 byte(s)
2005-08-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptGPGME.cpp (keycache_update): Reload OpenPGP parts
        of the secret key.
        (keycache_init): cache name of secret keyring.
        * wptKeyList.cpp (keylist_upd_key): Do not add long keyid.
        (get_key_type): Do not assume 'ultimate' means key pair.
        * wptKeyEditDlgs.cpp (diff_time): New.
        (keyedit_addsubkey_dlg_proc): Changed design and use
        diff_time. Drop checks for invalid keylength (< 1024, > 4096)
        because the combo box automatically handles this.
        * wptKeyManager.cpp (km_set_implicit_trust): Return error code.
        * wptGPG.cpp (get_backup_name): New.
        (gnupg_backup_keyrings): Rotate backup names, from 0..3.
        * wptClipImportDialog.cpp (clip_import_dlg_proc): Free memory.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Use 0x short keyid and
        not the long keyid.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26