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

Contents of /trunk/MyGPGME/encrypt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations)
Mon Apr 4 07:01:43 2005 UTC (19 years, 10 months ago) by twoaday
File MIME type: text/plain
File size: 15652 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 /* encrypt.c - Encrypt functions
2 * Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH
3 * Copyright (C) 2002-2005 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 Foundation,
19 * 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
27 #include "util.h"
28 #include "context.h"
29 #include "ops.h"
30
31
32 #define use_symmetric(rset) (!(rset) || !gpgme_recipients_count ((rset)))
33
34 struct recp_info_s {
35 struct recp_info_s * next;
36 gpgme_error_t code;
37 char recp[1];
38 };
39
40 struct encrypt_result_s {
41 int okay;
42 int no_recp;
43 int inv_recp;
44 int file_start;
45 int file_done;
46 struct recp_info_s * inf;
47 };
48
49
50 static gpgme_error_t
51 create_result_struct( gpgme_ctx_t ctx )
52 {
53 assert ( !ctx->result.encrypt );
54 ctx->result.encrypt = calloc( 1, sizeof *ctx->result.encrypt );
55 if( !ctx->result.encrypt )
56 return mk_error( Out_Of_Core );
57 ctx->result_type = RESULT_TYPE_ENCRYPT;
58 return 0;
59 } /* create_result_struct */
60
61
62 static gpgme_error_t
63 add_recp_info( _encrypt_result_t res, int code, const char * name )
64 {
65 struct recp_info_s * r;
66
67 r = calloc( 1, sizeof * r + strlen( name ) + 1 );
68 if( !r )
69 return mk_error( Out_Of_Core );
70 r->code = code;
71 strcpy (r->recp , name);
72 r->next = res->inf;
73 res->inf = r;
74
75 return 0;
76 } /* add_recp_info */
77
78
79 void
80 _gpgme_release_encrypt_result( _encrypt_result_t res )
81 {
82 struct recp_info_s * r, * r2;
83
84 if( !res )
85 return;
86 r = res->inf;
87 while( r ) {
88 r2 = r->next;
89 safe_free( r );
90 r = r2;
91 }
92 safe_free( res->inf );
93 safe_free( res );
94 } /* _gpgme_release_encrypt_result */
95
96
97 void
98 _gpgme_encrypt_add_cipher (gpgme_ctx_t ctx)
99 {
100 if (ctx->cipher_algo == -1)
101 return;
102 _gpgme_gpg_add_arg (ctx->gpg, "--cipher-algo");
103 switch (ctx->cipher_algo) {
104 case GPGME_CIPHER_3DES: _gpgme_gpg_add_arg (ctx->gpg, "3DES");break;
105 case GPGME_CIPHER_CAST5: _gpgme_gpg_add_arg (ctx->gpg, "CAST5");break;
106 case GPGME_CIPHER_BLOWFISH: _gpgme_gpg_add_arg (ctx->gpg, "BLOWFISH");break;
107 case GPGME_CIPHER_AES128: _gpgme_gpg_add_arg (ctx->gpg, "AES");break;
108 case GPGME_CIPHER_AES192: _gpgme_gpg_add_arg (ctx->gpg, "AES192");break;
109 case GPGME_CIPHER_AES256: _gpgme_gpg_add_arg (ctx->gpg, "AES256");break;
110 case GPGME_CIPHER_TWOFISH: _gpgme_gpg_add_arg (ctx->gpg, "TWOFISH");break;
111 default: _gpgme_gpg_add_arg (ctx->gpg, "AES");break;
112 }
113 if (ctx->s2k.used) {
114 char buf[32];
115 if (ctx->s2k.mode < 0 || ctx->s2k.mode > 3)
116 ctx->s2k.mode = GPGME_S2K_ITERSALTED;
117 sprintf( buf, "%d", ctx->s2k.mode );
118 _gpgme_gpg_add_arg (ctx->gpg, "--s2k-mode");
119 _gpgme_gpg_add_arg (ctx->gpg, buf);
120 _gpgme_gpg_add_arg (ctx->gpg, "--s2k-digest-algo");
121 switch (ctx->s2k.digest_algo) {
122 case GPGME_MD_SHA1: _gpgme_gpg_add_arg (ctx->gpg, "SHA1"); break;
123 case GPGME_MD_RMD160:_gpgme_gpg_add_arg (ctx->gpg, "RIPEMD160"); break;
124 default: _gpgme_gpg_add_arg (ctx->gpg, "SHA1"); break;
125 }
126 }
127 } /* _gpgme_encrypt_add_cipher */
128
129
130 static void
131 encrypt_status_handler( gpgme_ctx_t ctx, gpg_statcode_t code, char * args )
132 {
133 int i = 0;
134 gpgme_error_t err;
135
136 if (ctx->out_of_core)
137 return;
138
139 if( ctx->result_type == RESULT_TYPE_NONE ) {
140 if( create_result_struct ( ctx ) ) {
141 ctx->out_of_core = 1;
142 return;
143 }
144 }
145 assert( ctx->result_type == RESULT_TYPE_ENCRYPT );
146
147 switch( code ) {
148 case STATUS_END_ENCRYPTION:
149 ctx->result.encrypt->okay = 1;
150 break;
151
152 case STATUS_NO_RECP:
153 ctx->result.encrypt->no_recp = 1;
154 break;
155
156 case STATUS_INV_RECP:
157 while( args[i] && args[i] != ' ' )
158 i++;
159 while( args[i] && args[i] != ' ' )
160 i++;
161 err = add_recp_info( ctx->result.encrypt, atol( args ), args + i );
162 if( err )
163 ctx->out_of_core = 1;
164 ctx->result.encrypt->inv_recp++;
165 break;
166
167 case STATUS_FILE_START:
168 ctx->result.encrypt->file_start++;
169 if( ctx->cb.interactiv )
170 ctx->cb.interactiv( ctx->cb.interactiv_value, code, NULL, args+2 );
171 break;
172
173 case STATUS_FILE_DONE:
174 ctx->result.encrypt->file_done++;
175 if( ctx->cb.interactiv )
176 ctx->cb.interactiv( ctx->cb.interactiv_value, code, NULL, NULL );
177 break;
178
179 case STATUS_PROGRESS:
180 if (ctx->cb.progress)
181 _gpgme_progress_handler (ctx, args);
182 break;
183 }
184 } /* encrypt_status_handler */
185
186
187 static const char *
188 encrypt_command_handler (void * opaque, gpg_statcode_t code, const char * key)
189 {
190 gpgme_ctx_t ctx = opaque;
191
192 if (!ctx)
193 return NULL;
194 if (!strcmp (key, "untrusted_key.override"))
195 return "N";
196 if (!ctx->cb.interactiv)
197 return NULL;
198 if ((code == STATUS_GET_BOOL && !strcmp (key, "openfile.overwrite.okay"))
199 ||(code == STATUS_GET_LINE && !strcmp (key, "openfile.askoutname" )) )
200 return ctx->cb.interactiv (ctx->cb.interactiv_value, code, key, NULL);
201
202 return NULL;
203 } /* encrypt_command_handler */
204
205
206 static gpgme_error_t
207 encrypt_start( gpgme_ctx_t ctx, gpgme_recipients_t recp,
208 gpgme_data_t plain, gpgme_data_t ciph )
209
210 {
211 gpgme_error_t rc = 0;
212
213 fail_on_pending_request (ctx);
214 ctx->pending = 1;
215
216 /* do some checks */
217 if( !gpgme_recipients_count ( recp ) ) {
218 rc = mk_error( No_Recipients );
219 goto leave;
220 }
221
222 /* create a process object */
223 _gpgme_gpg_release (&ctx->gpg);
224 rc = _gpgme_gpg_new (&ctx->gpg);
225 if (rc)
226 goto leave;
227
228 _gpgme_gpg_set_status_handler (ctx->gpg, encrypt_status_handler, ctx);
229 _gpgme_gpg_set_command_handler (ctx->gpg, encrypt_command_handler, ctx);
230
231 /* build the commandline */
232 _gpgme_gpg_add_arg( ctx->gpg, "--encrypt" );
233 if( ctx->use_armor )
234 _gpgme_gpg_add_arg( ctx->gpg, "--armor" );
235 if (ctx->no_compress)
236 _gpgme_gpg_add_arg (ctx->gpg, "-z 0");
237 if (ctx->force_mdc)
238 _gpgme_gpg_add_arg (ctx->gpg, "--force-mdc");
239 _gpgme_add_comment (ctx);
240 if (ctx->cb.progress)
241 _gpgme_gpg_add_arg (ctx->gpg, "--enable-progress-filter");
242 /* If we know that all recipients are valid (full or ultimate trust)
243 we can pass suppress further checks */
244 if( ctx->force_trust || _gpgme_recipients_all_valid( recp ) )
245 _gpgme_gpg_add_arg( ctx->gpg, "--always-trust" );
246
247 _gpgme_append_gpg_args_from_recipients( recp, ctx->gpg );
248 if (ctx->use_logging)
249 _gpgme_gpg_set_logging_handler (ctx->gpg, ctx);
250
251 /* Check the supplied data */
252 if( gpgme_data_get_type( plain ) == GPGME_DATA_TYPE_NONE ) {
253 rc = mk_error( No_Data );
254 goto leave;
255 }
256 _gpgme_data_set_mode( plain, GPGME_DATA_MODE_OUT );
257 if( !ciph || gpgme_data_get_type( ciph ) != GPGME_DATA_TYPE_NONE ) {
258 rc = mk_error( Invalid_Value );
259 goto leave;
260 }
261 _gpgme_data_set_mode( ciph, GPGME_DATA_MODE_IN );
262 /* Tell the gpg object about the data */
263 if( ctx->use_tmpfiles ) {
264 _gpgme_gpg_add_arg( ctx->gpg, "--yes" );
265 _gpgme_gpg_add_arg( ctx->gpg, "--output" );
266 _gpgme_gpg_add_arg( ctx->gpg, _gpgme_get_tmpfile( 0 ) );
267 _gpgme_data_write_to_tmpfile( plain );
268 _gpgme_gpg_add_arg( ctx->gpg, _gpgme_get_tmpfile( 1 ) );
269 }
270 else {
271 _gpgme_gpg_add_arg( ctx->gpg, "--output" );
272 _gpgme_gpg_add_arg( ctx->gpg, "-" );
273 _gpgme_gpg_add_data( ctx->gpg, ciph, 1 );
274 _gpgme_gpg_add_arg( ctx->gpg, "--" );
275 _gpgme_gpg_add_data( ctx->gpg, plain, 0 );
276 }
277
278 /* and kick off the process */
279 rc = _gpgme_gpg_spawn ( ctx->gpg, ctx );
280
281 leave:
282 if( rc ) {
283 ctx->pending = 0;
284 _gpgme_gpg_release( &ctx->gpg );
285 }
286
287 return rc;
288 } /* encrypt_start */
289
290
291 gpgme_error_t
292 file_encrypt_start( gpgme_ctx_t ctx, gpgme_recipients_t recp,
293 const char ** input, size_t nfiles, const char * output )
294 {
295 gpgme_error_t rc = 0;
296 int symmetric = 0;
297
298 if( !input )
299 return mk_error( Invalid_Value );
300
301 fail_on_pending_request( ctx );
302 ctx->pending = 1;
303
304 if( use_symmetric( recp ) )
305 symmetric = 1;
306
307 _gpgme_gpg_release( &ctx->gpg );
308 rc = _gpgme_gpg_new( &ctx->gpg );
309 if( rc ) {
310 gpgme_release( ctx );
311 return rc;
312 }
313
314 _gpgme_gpg_set_status_handler( ctx->gpg, encrypt_status_handler, ctx );
315 if( ctx->cb.interactiv )
316 _gpgme_gpg_set_command_handler( ctx->gpg, encrypt_command_handler, ctx );
317 else
318 _gpgme_gpg_add_arg (ctx->gpg, "--yes");
319 if( ctx->use_armor )
320 _gpgme_gpg_add_arg (ctx->gpg, "--armor");
321 if (ctx->no_compress)
322 _gpgme_gpg_add_arg (ctx->gpg, "-z 0");
323 if (ctx->force_mdc)
324 _gpgme_gpg_add_arg (ctx->gpg, "--force-mdc");
325 _gpgme_add_comment (ctx);
326 if( ctx->cb.progress )
327 _gpgme_gpg_add_arg( ctx->gpg, "--enable-progress-filter" );
328 if( !output )
329 _gpgme_gpg_add_arg( ctx->gpg, "--no-mangle-dos-filenames" );
330
331 if( symmetric ) {
332 _gpgme_gpg_add_arg( ctx->gpg, "--symmetric" );
333 _gpgme_encrypt_add_cipher( ctx );
334 rc = _gpgme_add_passphrase( ctx );
335 if( rc ) {
336 _gpgme_gpg_release( &ctx->gpg );
337 return rc;
338 }
339 }
340 else {
341 if( ctx->use_throwkeyid )
342 _gpgme_gpg_add_arg( ctx->gpg, "--throw-keyid" );
343 if( ctx->force_trust )
344 _gpgme_gpg_add_arg( ctx->gpg, "--always-trust" );
345 if( recp )
346 _gpgme_append_gpg_args_from_recipients( recp, ctx->gpg );
347 if( ctx->pipemode || nfiles > 1 )
348 _gpgme_gpg_add_arg( ctx->gpg, "--encrypt-files" );
349 else
350 _gpgme_gpg_add_arg( ctx->gpg, "--encrypt" );
351
352 }
353
354 /* we cannot use --output for --encrypt-files */
355 if( nfiles == 1 && !ctx->pipemode && output ) {
356 _gpgme_gpg_add_arg( ctx->gpg, "--output" );
357 _gpgme_gpg_add_arg( ctx->gpg, output );
358 }
359 while( nfiles-- )
360 _gpgme_gpg_add_arg( ctx->gpg, *input++ );
361 rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
362 if( rc ) {
363 ctx->pending = 0;
364 _gpgme_gpg_release( &ctx->gpg );
365 }
366
367 return rc;
368 } /* file_encrypt_start */
369
370
371 static gpgme_error_t
372 get_encrypt_result (gpgme_ctx_t ctx)
373 {
374 struct encrypt_result_s * res;
375 gpgme_error_t err = 0;
376 int rc;
377
378 assert (ctx->result.encrypt);
379 res = ctx->result.encrypt;
380 if (res->okay)
381 return mk_error( No_Error );
382 if (res->no_recp)
383 err = mk_error (No_Recipients);
384 else if (res->inv_recp)
385 err = mk_error (Inv_Recipients);
386 else if ((rc = gpgme_get_process_rc (ctx )) != 0) {
387 DEBUG1 ("gpg return code=%d\n", rc);
388 err = mk_error (Internal_GPG_Problem);
389 }
390 else if (!res->okay || (res->file_start != res->file_done))
391 err = mk_error (Encryption_Failed);
392 return err;
393 } /* get_encrypt_result */
394
395
396 /**
397 * gpgme_op_encrypt:
398 * @ctx: The context
399 * @recp: A set of recipients
400 * @in: plaintext input
401 * @out: ciphertext output
402 *
403 * This function encrypts @in to @out for all recipients from
404 * @recp. Other parameters are take from the context @c.
405 * The function does wait for the result.
406 *
407 * Return value: 0 on success or an errorcode.
408 **/
409 gpgme_error_t
410 gpgme_op_encrypt( gpgme_ctx_t ctx, gpgme_recipients_t recp,
411 gpgme_data_t in, gpgme_data_t out )
412
413 {
414 gpgme_error_t err;
415
416 err = encrypt_start( ctx, recp, in, out );
417 if( !err ) {
418 gpgme_wait( ctx, 1 );
419 ctx->pending = 0;
420 if( ctx->use_tmpfiles ) {
421 _gpgme_data_read_from_tmpfile( out );
422 _gpgme_del_tmpfiles( ctx->wipe_fnc );
423 }
424 err = get_encrypt_result( ctx );
425 }
426
427 return err;
428 } /* gpgme_op_encrypt */
429
430
431 gpgme_error_t
432 gpgme_op_file_encrypt( gpgme_ctx_t ctx, gpgme_recipients_t rset,
433 const char * input, const char * output )
434 {
435 gpgme_error_t err;
436 const char * files[1];
437
438 files[0] = input;
439 err = file_encrypt_start( ctx, rset, files, 1, output );
440 if( !err ) {
441 gpgme_wait( ctx, 1 );
442 ctx->pending = 0;
443 err = get_encrypt_result( ctx );
444 }
445
446 return err;
447 } /* gpgme_op_file_encrypt */
448
449
450 gpgme_error_t
451 gpgme_op_files_encrypt( gpgme_ctx_t ctx, gpgme_recipients_t rset,
452 const char ** files, size_t nfiles )
453 {
454 gpgme_error_t err;
455
456 /* fixme: the result is actually only for the last file. we need
457 a notification system which informs us with a callback
458 after each file is processed. */
459 if( use_symmetric( rset ) ) {
460 const char * s[1];
461 size_t i;
462
463 for( i=0; i < nfiles; i++ ) {
464 s[0] = files[i];
465 err = file_encrypt_start( ctx, NULL, s, 1, NULL );
466 if( !err ) {
467 gpgme_wait( ctx, 1 );
468 ctx->pending = 0;
469 err = get_encrypt_result( ctx );
470 }
471 if( err )
472 break;
473 }
474 }
475 else {
476 err = file_encrypt_start( ctx, rset, files, nfiles, NULL );
477 if( !err ) {
478 gpgme_wait( ctx, 1 );
479 ctx->pending = 0;
480 err = get_encrypt_result( ctx );
481 }
482 }
483 return err;
484 }
485
486
487 gpgme_error_t
488 gpgme_op_clip_encrypt( gpgme_recipients_t rset, int opts, gpgme_ctx_t *r_ctx )
489 {
490 gpgme_error_t err;
491 gpgme_ctx_t ctx = NULL;
492 gpgme_data_t plain = NULL;
493 gpgme_data_t ciph = NULL;
494
495 err = gpgme_new( &ctx );
496 if( err )
497 return err;
498
499 if( opts & GPGME_CTRL_TMPFILES )
500 gpgme_control( ctx, GPGME_CTRL_TMPFILES, 1 );
501 if( opts & GPGME_CTRL_FORCETRUST )
502 gpgme_control( ctx, GPGME_CTRL_FORCETRUST, 1 );
503 gpgme_control( ctx, GPGME_CTRL_ARMOR, 1 );
504
505 err = gpgme_data_new_from_clipboard (&plain);
506 if( !err )
507 err = gpgme_data_new( &ciph );
508 if( !err )
509 err = gpgme_op_encrypt( ctx, rset, plain, ciph );
510 if( !err ) {
511 gpgme_data_change_version( &ciph );
512 gpgme_data_release_and_set_clipboard( ciph );
513 }
514 if( r_ctx )
515 *r_ctx = ctx;
516 else
517 gpgme_release( ctx );
518 gpgme_data_release( plain );
519 return err;
520 } /* gpgme_op_clip_encrypt */
521
522
523 int
524 gpgme_recperr_count_items( gpgme_ctx_t ctx )
525 {
526 struct recp_info_s * r;
527 int ncount = 0;
528
529 if( !ctx )
530 return 0;
531 if( ctx->result_type != RESULT_TYPE_ENCRYPT )
532 return -1;
533 for( r = ctx->result.encrypt->inf; r; r = r->next )
534 ncount++;
535
536 return ncount;
537 } /* gpgme_recperr_count_items */
538
539
540 const char*
541 gpgme_recperr_get( gpgme_ctx_t ctx, int idx, gpgme_error_t *r_code )
542 {
543 struct recp_info_s * r;
544
545 if( !ctx )
546 return NULL;
547 if( idx > gpgme_recperr_count_items( ctx ) )
548 return NULL;
549 for( r = ctx->result.encrypt->inf; r && idx--; r = r->next )
550 ;
551 if( r ) {
552 if( r_code )
553 *r_code = r->code;
554 return r->recp;
555 }
556
557 return NULL;
558 } /* gpgme_recperr_get_code */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26