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

Contents of /trunk/MyGPGME/gpgme.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File MIME type: text/plain
File size: 14372 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


1 /* gpgme.c - My GnuPG Made Easy
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 <assert.h>
25 #include <windows.h>
26 #include <process.h>
27
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32 /**
33 * gpgme_new:
34 * @r_ctx: Returns the new context
35 *
36 * Create a new context to be used with most of the other GPGME
37 * functions. Use gpgme_release_contect() to release all resources
38 *
39 * Return value: An error code
40 **/
41 gpgme_error_t
42 gpgme_new (gpgme_ctx_t * r_ctx)
43 {
44 gpgme_ctx_t ctx;
45
46 if (!r_ctx)
47 return mk_error (Invalid_Value);
48 *r_ctx = NULL;
49 ctx = calloc (1, sizeof *ctx);
50 if (!ctx)
51 return mk_error (Out_Of_Core);
52 ctx->keylist_mode |= 8; /* include sigs */
53 ctx->cipher_algo = GPGME_CIPHER_AES128;
54 ctx->s2k.digest_algo = GPGME_MD_SHA1;
55 ctx->s2k.mode = GPGME_S2K_ITERSALTED;
56 *r_ctx = ctx;
57 return 0;
58 }
59
60 /**
61 * gpgme_release:
62 * @c: Context to be released.
63 *
64 * Release all resources associated with the given context.
65 **/
66 void
67 gpgme_release (gpgme_ctx_t ctx)
68 {
69 if (!ctx)
70 return;
71 _gpgme_gpg_release (&ctx->gpg);
72 _gpgme_release_result (ctx);
73 gpgme_key_release (ctx->tmp_key);
74 gpgme_data_release (ctx->help_data_1);
75 gpgme_data_release (ctx->notation);
76 gpgme_data_release (ctx->logging);
77 gpgme_signers_clear (ctx);
78 safe_free (ctx->signers);
79 safe_free (ctx->keygen_fpr);
80 safe_free (ctx->locusr);
81 safe_free (ctx->comment);
82 /* fixme: release the key_queue */
83 safe_free (ctx);
84 } /* gpgme_release */
85
86
87 void
88 _gpgme_release_result (gpgme_ctx_t c)
89 {
90 assert (c);
91 switch (c->result_type) {
92 case RESULT_TYPE_NONE:
93 break;
94
95 case RESULT_TYPE_EDITKEY:
96 _gpgme_release_editkey_result (c->result.editk);
97 break;
98
99 case RESULT_TYPE_ENCRYPT:
100 _gpgme_release_encrypt_result( c->result.encrypt );
101 break;
102
103 case RESULT_TYPE_VERIFY:
104 _gpgme_release_verify_result (c->result.verify);
105 break;
106
107 case RESULT_TYPE_DECRYPT:
108 _gpgme_release_decrypt_result (c->result.decrypt);
109 break;
110
111 case RESULT_TYPE_SIGN:
112 _gpgme_release_sign_result ( c->result.sign );
113 break;
114
115 case RESULT_TYPE_SIGN_ENCRYPT:
116 _gpgme_release_sign_encrypt_result( c->result.sign_enc );
117 break;
118
119 case RESULT_TYPE_IMPORT:
120 _gpgme_release_import_result( c->result.import );
121 break;
122
123 case RESULT_TYPE_SYMENC:
124 _gpgme_release_symenc_result( c->result.symenc );
125 break;
126 }
127
128 c->result.verify = NULL;
129 c->result_type = RESULT_TYPE_NONE;
130 } /* _gpgme_release_result */
131
132
133 /**
134 * gpgme_cancel:
135 * @c: the context
136 *
137 * Cancel the current operation. It is not guaranteed that it will work for
138 * all kinds of operations. It is especially useful in a passphrase callback
139 * to stop the system from asking another time for the passphrase.
140 **/
141 void
142 gpgme_cancel (gpgme_ctx_t c)
143 {
144 return_if_fail (c);
145 c->cancel = 1;
146 c->pending = 0;
147 } /* gpgme_cancel */
148
149
150 /**
151 * gpgme_get_notation:
152 * @c: the context
153 *
154 * If there is notation data available from the last signature check, this
155 * function may be used to return this notation data as a string. The string
156 * is a represantaton of that data embedded in a %<notation> container.
157 *
158 * Return value: An string or NULL if no notation data is available.
159 **/
160 char *
161 gpgme_get_notation (gpgme_ctx_t c)
162 {
163 if (!c || !c->notation)
164 return NULL;
165 return _gpgme_data_get_as_string (c->notation);
166 } /* gpgme_get_notation */
167
168
169 char *
170 gpgme_get_logging (gpgme_ctx_t c)
171 {
172 if (!c || !c->logging)
173 return NULL;
174 return _gpgme_data_get_as_string (c->logging);
175 }
176
177
178 void
179 gpgme_set_comment (gpgme_ctx_t c, const char * text)
180 {
181 if (!c)
182 return;
183 safe_free (c->comment);
184 c->comment = strdup (text);
185 if (!c->comment)
186 c->out_of_core = 1;
187 }
188
189
190 void
191 gpgme_set_homedir (gpgme_ctx_t c, const char *homedir)
192 {
193 if (!c)
194 return;
195 safe_free (c->homedir);
196 c->homedir = strdup (homedir);
197 if (!c->homedir)
198 c->out_of_core = 1;
199 }
200
201
202 /**
203 * gpgme_control:
204 * @c: the context
205 * @cmd: command to set
206 * @val: the value for the command.
207 *
208 * This is a replace for gpgme_set_xxx because in a DLL it's better to
209 * reduce the amount of functions.
210 **/
211 void *
212 gpgme_control( gpgme_ctx_t c, int cmd, int val )
213 {
214 if( !c )
215 return 0;
216
217 if( val == -1 ) {
218 switch( cmd ) {
219 case GPGME_CTRL_ARMOR: return (int *)c->use_armor;
220 case GPGME_CTRL_FPR: return c->keygen_fpr;
221 default: return NULL;
222 }
223 }
224
225 switch( cmd ) {
226
227 case GPGME_CTRL_S2K:
228 /* Pass S2K options down to GPG (no=0, yes=1) */
229 c->s2k.used = val;
230 break;
231
232 case GPGME_CTRL_S2K_MODE:
233 c->s2k.mode = val;
234 break;
235
236 case GPGME_CTRL_S2K_HASH:
237 c->s2k.digest_algo = val;
238 break;
239
240 case GPGME_CTRL_TEXTMODE:
241 /* Enable or disable the use of the special textmode. Textmode is for example
242 used for MIME (RFC2015) signatures. */
243 c->use_textmode = val;
244 break;
245
246 case GPGME_CTRL_LISTMODE:
247 /* This function changes the default behaviour of the keylisting functions.
248 Defines values for @mode are: %0 = normal, %1 = fast listing without
249 information about key validity. */
250 c->keylist_mode |= val;
251 break;
252
253 case GPGME_CTRL_NO_COMPR:
254 c->no_compress = val;
255 c->force_mdc = val == 1? 1 : 0;
256 break;
257
258 case GPGME_CTRL_CIPHER:
259 if (val == -1) { /* disable it */
260 c->cipher_algo = -1;
261 break;
262 }
263 if (val < 1 || val > 7) {
264 c->cipher_algo = GPGME_CIPHER_CAST5;
265 break;
266 }
267 c->cipher_algo = val;
268 break;
269
270 case GPGME_CTRL_TMPFILES: c->use_tmpfiles = val; break;
271 case GPGME_CTRL_WITH_SECRET_KEY: c->with_secret_key = val; break;
272 case GPGME_CTRL_FORCETRUST: c->force_trust = val; break;
273 case GPGME_CTRL_FORCEOPT: c->force_opt = val; break;
274 case GPGME_CTRL_FILE: c->use_file = val; break;
275 case GPGME_CTRL_THROWKEYID: c->use_throwkeyid = val; break;
276 case GPGME_CTRL_ARMOR: c->use_armor = val; break;
277 case GPGME_CTRL_INTERACTIVE: c->use_interactive = val; break;
278 case GPGME_CTRL_PIPEMODE: c->use_pipemode = val; break;
279 case GPGME_CTRL_LOGGING: c->use_logging = val; break;
280 case GPGME_CTRL_CB_VAL: c->cb.progress_value_int = val; break;
281 }
282
283 return NULL;
284 }
285
286 /**
287 * gpgme_set_passphrase_cb:
288 * @c: the context
289 * @cb: A callback function
290 * @cb_value: The value passed to the callback function
291 *
292 * This function sets a callback function to be used to pass a passphrase
293 * to gpg. The preferred way to handle this is by using the gpg-agent, but
294 * because that beast is not ready for real use, you can use this passphrase
295 * thing.
296 *
297 * The callback function is defined as:
298 * <literal>
299 * typedef const char *(*gpgme_passphrase_cb_t)(void*cb_value,
300 * const char *desc,
301 * void *r_hd);
302 * </literal>
303 * and called whenever gpgme needs a passphrase. DESC will have a nice
304 * text, to be used to prompt for the passphrase and R_HD is just a parameter
305 * to be used by the callback it self. Becuase the callback returns a const
306 * string, the callback might want to know when it can release resources
307 * assocated with that returned string; gpgme helps here by calling this
308 * passphrase callback with an DESC of %NULL as soon as it does not need
309 * the returned string anymore. The callback function might then choose
310 * to release resources depending on R_HD.
311 *
312 **/
313 void
314 gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb,
315 void * cb_value)
316 {
317 if (!ctx)
318 return;
319 ctx->cb.passphrase = cb;
320 ctx->cb.passphrase_value = cb_value;
321 } /* gpgme_set_passphrase_cb */
322
323
324 void
325 gpgme_set_interactive_cb (gpgme_ctx_t ctx, gpgme_interactive_cb_t cb,
326 void * cb_value)
327 {
328 if (!ctx)
329 return;
330 ctx->cb.interactiv = cb;
331 ctx->cb.interactiv_value = cb_value;
332 } /* gpgme_set_inteactive_cb */
333
334
335 /**
336 * gpgme_set_pprogress_cb:
337 * @c: the context
338 * @cb: A callback function
339 * @cb_value: The value passed to the callback function
340 *
341 * This function sets a callback function to be used as a progress indicator.
342 *
343 * The callback function is defined as:
344 * <literal>
345 * typedef void (*gpgme_progress_cb_t) (void * cb_value,
346 * const char * what, int type,
347 * int curretn, int total);
348 * </literal>
349 * For details on the progress events, see the entry for the PROGRESS
350 * status in the file doc/DETAILS of the GnuPG distribution.
351 **/
352 void
353 gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb,
354 void * cb_value)
355 {
356 if (!ctx)
357 return;
358 ctx->cb.progress = cb;
359 ctx->cb.progress_value = cb_value;
360 } /* gpgme_set_progress_cb */
361
362
363 void
364 gpgme_set_edit_ctx( gpgme_ctx_t ctx, void * edit_ctx, int edit_id )
365 {
366 if( !ctx )
367 return;
368 ctx->edit_opaque = edit_ctx;
369 ctx->edit_cmd = edit_id;
370 } /* gpgme_set_edit_ctx */
371
372
373 void
374 gpgme_set_list_options (gpgme_ctx_t ctx, int optid)
375 {
376 if (!ctx)
377 return;
378 ctx->list_opts |= optid;
379 }
380
381
382 void
383 gpgme_set_cache_ctx (gpgme_ctx_t ctx, void * cache_ctx)
384 {
385 if( ctx )
386 ctx->key_lookup = cache_ctx;
387 } /* gpgme_set_cache_ctx */
388
389
390 void
391 gpgme_set_passphrase( gpgme_ctx_t ctx, const char * passphrase )
392 {
393 if( !ctx )
394 return;
395 ctx->passphrase_value = passphrase;
396 ctx->use_pass_fd = 1;
397 } /* gpgme_set_passphrase */
398
399
400 gpgme_error_t
401 _gpgme_add_passphrase( gpgme_ctx_t ctx )
402 {
403 gpgme_error_t err;
404 gpgme_data_t passphrase_fd;
405
406 if( !ctx )
407 return mk_error( Invalid_Value );
408 if( !ctx->passphrase_value || !ctx->use_pass_fd )
409 return mk_error( General_Error );
410
411 err = gpgme_data_new_from_mem( &passphrase_fd, ctx->passphrase_value,
412 strlen( ctx->passphrase_value ), 0 );
413 if( err )
414 return err;
415 _gpgme_data_set_mode( passphrase_fd, GPGME_DATA_MODE_OUT );
416 _gpgme_gpg_add_arg( ctx->gpg, "--passphrase-fd" );
417 _gpgme_gpg_add_data( ctx->gpg, passphrase_fd, -2 );
418
419 return 0;
420 } /* _gpgme_add_passphrase */
421
422
423 void
424 gpgme_set_debug_mode( int val )
425 {
426 if( val )
427 putenv( "GPGME_DEBUG=5:gpgme.dbg" );
428 else
429 putenv( "GPGME_DEBUG=" );
430 } /* gpgme_set_debug_mode */
431
432
433 const char*
434 _gpgme_get_tmpfile( int input )
435 {
436 static char tmpfile[384];
437 char path[256];
438
439 GetTempPath( sizeof path -1, path );
440 _snprintf( tmpfile, sizeof tmpfile -1,
441 "%sgpgme%s.%u", path, input? "IN" : "OUT", getpid() );
442 return tmpfile;
443 } /* _gpgme_get_tmpfile */
444
445
446 static int
447 _gpgme_unlink( const char * file, int arg )
448 {
449 return unlink( file );
450 } /* _gpgme_unlink */
451
452
453 void
454 _gpgme_del_tmpfiles( gpgme_wipe_t wipe_fnc )
455 {
456 gpgme_wipe_t erase = wipe_fnc? wipe_fnc: (gpgme_wipe_t)_gpgme_unlink;
457
458 erase( _gpgme_get_tmpfile( 0 ), 1 );
459 erase( _gpgme_get_tmpfile( 1 ), 1 );
460 } /* _gpgme_del_tmpfiles */
461
462 void
463 gpgme_set_wipe_fnc( gpgme_ctx_t ctx, gpgme_wipe_t fnc )
464 {
465 if( ctx )
466 ctx->wipe_fnc = fnc;
467 } /* gpgme_set_wipe_fnc */
468
469
470 void
471 gpgme_set_local_user( gpgme_ctx_t ctx, const char * name )
472 {
473 if( ctx && name ) {
474 safe_free (ctx->locusr);
475 ctx->locusr = strdup( name );
476 }
477 } /* gpgme_set_local_user */
478
479
480 int
481 gpgme_get_process_rc (gpgme_ctx_t ctx)
482 {
483 if (!ctx)
484 return -1;
485 return (int)ctx->proc_rc;
486 } /* gpgme_get_process_rc */
487
488
489 void
490 _gpgme_progress_handler (gpgme_ctx_t ctx, char * args)
491 {
492 const char * name = args;
493 char * buf, * p;
494 char * what = NULL;
495 unsigned curr, total, i=0;
496
497 /* what */
498 p = strchr (args, '?');
499 if (!p)
500 return;
501 what = malloc (p-args+2);
502 if (!what) {
503 ctx->out_of_core = 1;
504 return;
505 }
506 while (name && *name != '?')
507 what[i++] = *name++;
508 what[i] = '\0';
509 /* XXX remove space at the end */
510 i = 0;
511 buf = args + (p-args);
512 while ((p = strsep (&buf, " ")) != NULL) {
513 switch (i) {
514 case 0:
515 break; /* type */
516 case 1:
517 curr = strtoul (p, NULL, 10);
518 break; /* current offset */
519 case 2:
520 total = strtoul (p, NULL, 10);
521 break; /* total */
522 }
523 i++;
524 }
525 if (what) {
526 ctx->cb.progress (ctx->cb.progress_value, what, 0, curr, total);
527 safe_free (what);
528 }
529 } /* _gpgme_progress_handler */
530
531
532 void
533 _gpgme_add_comment (gpgme_ctx_t ctx)
534 {
535 char * p;
536
537 if (ctx->comment) {
538 p = calloc (1, strlen (ctx->comment)+3);
539 if (!p) {
540 ctx->out_of_core = 1;
541 return;
542 }
543 _gpgme_gpg_add_arg (ctx->gpg, "--comment");
544 p[0] = '"';
545 strcpy (p+1, ctx->comment);
546 strcat (p, "\"");
547 _gpgme_gpg_add_arg (ctx->gpg, p);
548 safe_free (p);
549 }
550 }
551
552
553 gpgme_error_t
554 gpgme_check_logging (gpgme_ctx_t ctx)
555 {
556 char * buf;
557
558 if (!ctx)
559 return mk_error (Invalid_Value);
560 buf = gpgme_get_logging (ctx);
561 if (!buf)
562 return mk_error (No_Error);
563
564 /* XXX: this only works for English GPG output!!! */
565 if (strstr (buf, "gpg.conf:") && strstr (buf, "invalid option"))
566 return mk_error (Conf_InvOption);
567
568 free (buf);
569 return 0;
570 }
571
572
573 gpgme_error_t
574 gpgme_lib_init (void)
575 {
576 return 0;
577 }
578
579
580 void
581 gpgme_lib_cleanup (void)
582 {
583 debug_cleanup ();
584 rungpg_cleanup ();
585 io_cleanup ();
586 wait_cleanup ();
587 util_cleanup ();
588 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26