Line data Source code
1 : /* engine.c - GPGME engine support.
2 : Copyright (C) 2000 Werner Koch (dd9jn)
3 : Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009, 2010 g10 Code GmbH
4 :
5 : This file is part of GPGME.
6 :
7 : GPGME is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU Lesser General Public License as
9 : published by the Free Software Foundation; either version 2.1 of
10 : the License, or (at your option) any later version.
11 :
12 : GPGME is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : Lesser General Public License for more details.
16 :
17 : You should have received a copy of the GNU Lesser General Public
18 : License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 : #include <stdlib.h>
25 : #include <string.h>
26 : #include <errno.h>
27 : #include <assert.h>
28 :
29 : #include "gpgme.h"
30 : #include "util.h"
31 : #include "sema.h"
32 : #include "ops.h"
33 : #include "debug.h"
34 :
35 : #include "engine.h"
36 : #include "engine-backend.h"
37 :
38 :
39 : struct engine
40 : {
41 : struct engine_ops *ops;
42 : void *engine;
43 : };
44 :
45 :
46 : static struct engine_ops *engine_ops[] =
47 : {
48 : &_gpgme_engine_ops_gpg, /* OpenPGP. */
49 : &_gpgme_engine_ops_gpgsm, /* CMS. */
50 : &_gpgme_engine_ops_gpgconf, /* gpg-conf. */
51 : &_gpgme_engine_ops_assuan, /* Low-Level Assuan. */
52 : &_gpgme_engine_ops_g13, /* Crypto VFS. */
53 : #ifdef ENABLE_UISERVER
54 : &_gpgme_engine_ops_uiserver, /* UI-Server. */
55 : #else
56 : NULL,
57 : #endif
58 : &_gpgme_engine_ops_spawn
59 : };
60 :
61 :
62 : /* The engine info. */
63 : static gpgme_engine_info_t engine_info;
64 : DEFINE_STATIC_LOCK (engine_info_lock);
65 :
66 : /* If non-NULL, the minimal version required for all engines. */
67 : static char *engine_minimal_version;
68 :
69 :
70 :
71 : /* Get the file name of the engine for PROTOCOL. */
72 : static const char *
73 392 : engine_get_file_name (gpgme_protocol_t proto)
74 : {
75 392 : if (proto > DIM (engine_ops))
76 0 : return NULL;
77 :
78 392 : if (engine_ops[proto] && engine_ops[proto]->get_file_name)
79 392 : return (*engine_ops[proto]->get_file_name) ();
80 : else
81 0 : return NULL;
82 : }
83 :
84 :
85 : /* Get the standard home dir of the engine for PROTOCOL. */
86 : static const char *
87 472 : engine_get_home_dir (gpgme_protocol_t proto)
88 : {
89 472 : if (proto > DIM (engine_ops))
90 0 : return NULL;
91 :
92 472 : if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
93 56 : return (*engine_ops[proto]->get_home_dir) ();
94 : else
95 416 : return NULL;
96 : }
97 :
98 :
99 : /* Get a malloced string containing the version number of the engine
100 : * for PROTOCOL. If this function returns NULL for a valid protocol,
101 : * it should be assumed that the engine is a pseudo engine. */
102 : static char *
103 472 : engine_get_version (gpgme_protocol_t proto, const char *file_name)
104 : {
105 472 : if (proto > DIM (engine_ops))
106 0 : return NULL;
107 :
108 472 : if (engine_ops[proto] && engine_ops[proto]->get_version)
109 472 : return (*engine_ops[proto]->get_version) (file_name);
110 : else
111 0 : return NULL;
112 : }
113 :
114 :
115 : /* Get the required version number of the engine for PROTOCOL. This
116 : * may be NULL. */
117 : static const char *
118 336 : engine_get_req_version (gpgme_protocol_t proto)
119 : {
120 336 : if (proto > DIM (engine_ops))
121 0 : return NULL;
122 :
123 336 : if (engine_ops[proto] && engine_ops[proto]->get_req_version)
124 336 : return (*engine_ops[proto]->get_req_version) ();
125 : else
126 0 : return NULL;
127 : }
128 :
129 :
130 : /* Verify the version requirement for the engine for PROTOCOL. */
131 : gpgme_error_t
132 115 : gpgme_engine_check_version (gpgme_protocol_t proto)
133 : {
134 : gpgme_error_t err;
135 : gpgme_engine_info_t info;
136 : int result;
137 :
138 115 : LOCK (engine_info_lock);
139 115 : info = engine_info;
140 115 : if (!info)
141 : {
142 : /* Make sure it is initialized. */
143 52 : UNLOCK (engine_info_lock);
144 52 : err = gpgme_get_engine_info (&info);
145 52 : if (err)
146 0 : return err;
147 :
148 52 : LOCK (engine_info_lock);
149 : }
150 :
151 240 : while (info && info->protocol != proto)
152 10 : info = info->next;
153 :
154 115 : if (!info)
155 0 : result = 0;
156 : else
157 115 : result = _gpgme_compare_versions (info->version,
158 115 : info->req_version);
159 :
160 115 : UNLOCK (engine_info_lock);
161 115 : return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
162 : }
163 :
164 :
165 : /* Release the engine info INFO. */
166 : void
167 222 : _gpgme_engine_info_release (gpgme_engine_info_t info)
168 : {
169 1776 : while (info)
170 : {
171 1332 : gpgme_engine_info_t next_info = info->next;
172 :
173 1332 : if (info->file_name)
174 1332 : free (info->file_name);
175 1332 : if (info->home_dir)
176 222 : free (info->home_dir);
177 1332 : if (info->version)
178 1332 : free (info->version);
179 1332 : free (info);
180 1332 : info = next_info;
181 : }
182 222 : }
183 :
184 :
185 : /* This is an internal function to set a mimimal required version.
186 : * This function must only be called by gpgme_set_global_flag.
187 : * Returns 0 on success. */
188 : int
189 0 : _gpgme_set_engine_minimal_version (const char *value)
190 : {
191 0 : free (engine_minimal_version);
192 0 : if (value)
193 : {
194 0 : engine_minimal_version = strdup (value);
195 0 : return !engine_minimal_version;
196 : }
197 : else
198 : {
199 0 : engine_minimal_version = NULL;
200 0 : return 0;
201 : }
202 : }
203 :
204 :
205 : /* Get the information about the configured and installed engines. A
206 : pointer to the first engine in the statically allocated linked list
207 : is returned in *INFO. If an error occurs, it is returned. The
208 : returned data is valid until the next gpgme_set_engine_info. */
209 : gpgme_error_t
210 60 : gpgme_get_engine_info (gpgme_engine_info_t *info)
211 : {
212 : gpgme_error_t err;
213 :
214 60 : LOCK (engine_info_lock);
215 60 : if (!engine_info)
216 : {
217 56 : gpgme_engine_info_t *lastp = &engine_info;
218 56 : gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
219 : GPGME_PROTOCOL_CMS,
220 : GPGME_PROTOCOL_GPGCONF,
221 : GPGME_PROTOCOL_ASSUAN,
222 : GPGME_PROTOCOL_G13,
223 : GPGME_PROTOCOL_UISERVER,
224 : GPGME_PROTOCOL_SPAWN };
225 : unsigned int proto;
226 :
227 56 : err = 0;
228 448 : for (proto = 0; proto < DIM (proto_list); proto++)
229 : {
230 392 : const char *ofile_name = engine_get_file_name (proto_list[proto]);
231 392 : const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
232 392 : char *version = engine_get_version (proto_list[proto], NULL);
233 : char *file_name;
234 : char *home_dir;
235 :
236 392 : if (!ofile_name)
237 56 : continue;
238 :
239 336 : file_name = strdup (ofile_name);
240 336 : if (!file_name)
241 0 : err = gpg_error_from_syserror ();
242 :
243 336 : if (ohome_dir)
244 : {
245 56 : home_dir = strdup (ohome_dir);
246 56 : if (!home_dir && !err)
247 0 : err = gpg_error_from_syserror ();
248 : }
249 : else
250 280 : home_dir = NULL;
251 :
252 336 : *lastp = calloc (1, sizeof (*engine_info));
253 336 : if (!*lastp && !err)
254 0 : err = gpg_error_from_syserror ();
255 :
256 : /* Check against the optional minimal engine version. */
257 336 : if (!err && version && engine_minimal_version
258 0 : && !_gpgme_compare_versions (version, engine_minimal_version))
259 : {
260 : #if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
261 : err = gpg_error (GPG_ERR_NO_ENGINE);
262 : #else
263 0 : err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
264 : #endif
265 : }
266 :
267 : /* Now set the dummy version for pseudo engines. */
268 336 : if (!err && !version)
269 : {
270 168 : version = strdup ("1.0.0");
271 168 : if (!version)
272 0 : err = gpg_error_from_syserror ();
273 : }
274 :
275 336 : if (err)
276 : {
277 0 : _gpgme_engine_info_release (engine_info);
278 0 : engine_info = NULL;
279 :
280 0 : if (file_name)
281 0 : free (file_name);
282 0 : if (home_dir)
283 0 : free (home_dir);
284 0 : if (version)
285 0 : free (version);
286 :
287 0 : UNLOCK (engine_info_lock);
288 0 : return err;
289 : }
290 :
291 336 : (*lastp)->protocol = proto_list[proto];
292 336 : (*lastp)->file_name = file_name;
293 336 : (*lastp)->home_dir = home_dir;
294 336 : (*lastp)->version = version;
295 336 : (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
296 336 : if (!(*lastp)->req_version)
297 168 : (*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
298 336 : (*lastp)->next = NULL;
299 336 : lastp = &(*lastp)->next;
300 : }
301 : }
302 :
303 60 : *info = engine_info;
304 60 : UNLOCK (engine_info_lock);
305 60 : return 0;
306 : }
307 :
308 :
309 : /* Get a deep copy of the engine info and return it in INFO. */
310 : gpgme_error_t
311 225 : _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
312 : {
313 225 : gpgme_error_t err = 0;
314 : gpgme_engine_info_t info;
315 : gpgme_engine_info_t new_info;
316 : gpgme_engine_info_t *lastp;
317 :
318 225 : LOCK (engine_info_lock);
319 225 : info = engine_info;
320 225 : if (!info)
321 : {
322 : /* Make sure it is initialized. */
323 1 : UNLOCK (engine_info_lock);
324 1 : err = gpgme_get_engine_info (&info);
325 1 : if (err)
326 0 : return err;
327 :
328 1 : LOCK (engine_info_lock);
329 : }
330 :
331 225 : new_info = NULL;
332 225 : lastp = &new_info;
333 :
334 1800 : while (info)
335 : {
336 : char *file_name;
337 : char *home_dir;
338 : char *version;
339 :
340 1350 : assert (info->file_name);
341 1350 : file_name = strdup (info->file_name);
342 1350 : if (!file_name)
343 0 : err = gpg_error_from_syserror ();
344 :
345 1350 : if (info->home_dir)
346 : {
347 225 : home_dir = strdup (info->home_dir);
348 225 : if (!home_dir && !err)
349 0 : err = gpg_error_from_syserror ();
350 : }
351 : else
352 1125 : home_dir = NULL;
353 :
354 1350 : if (info->version)
355 : {
356 1350 : version = strdup (info->version);
357 1350 : if (!version && !err)
358 0 : err = gpg_error_from_syserror ();
359 : }
360 : else
361 0 : version = NULL;
362 :
363 1350 : *lastp = malloc (sizeof (*engine_info));
364 1350 : if (!*lastp && !err)
365 0 : err = gpg_error_from_syserror ();
366 :
367 1350 : if (err)
368 : {
369 0 : _gpgme_engine_info_release (new_info);
370 0 : if (file_name)
371 0 : free (file_name);
372 0 : if (home_dir)
373 0 : free (home_dir);
374 0 : if (version)
375 0 : free (version);
376 :
377 0 : UNLOCK (engine_info_lock);
378 0 : return err;
379 : }
380 :
381 1350 : (*lastp)->protocol = info->protocol;
382 1350 : (*lastp)->file_name = file_name;
383 1350 : (*lastp)->home_dir = home_dir;
384 1350 : (*lastp)->version = version;
385 1350 : (*lastp)->req_version = info->req_version;
386 1350 : (*lastp)->next = NULL;
387 1350 : lastp = &(*lastp)->next;
388 :
389 1350 : info = info->next;
390 : }
391 :
392 225 : *r_info = new_info;
393 225 : UNLOCK (engine_info_lock);
394 225 : return 0;
395 : }
396 :
397 :
398 : /* Set the engine info for the info list INFO, protocol PROTO, to the
399 : file name FILE_NAME and the home directory HOME_DIR. */
400 : gpgme_error_t
401 80 : _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
402 : const char *file_name, const char *home_dir)
403 : {
404 : char *new_file_name;
405 : char *new_home_dir;
406 : char *new_version;
407 :
408 : /* FIXME: Use some PROTO_MAX definition. */
409 80 : if (proto > DIM (engine_ops))
410 0 : return gpg_error (GPG_ERR_INV_VALUE);
411 :
412 161 : while (info && info->protocol != proto)
413 1 : info = info->next;
414 :
415 80 : if (!info)
416 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
417 :
418 : /* Prepare new members. */
419 80 : if (file_name)
420 80 : new_file_name = strdup (file_name);
421 : else
422 : {
423 0 : const char *ofile_name = engine_get_file_name (proto);
424 0 : assert (ofile_name);
425 0 : new_file_name = strdup (ofile_name);
426 : }
427 80 : if (!new_file_name)
428 0 : return gpg_error_from_syserror ();
429 :
430 80 : if (home_dir)
431 : {
432 0 : new_home_dir = strdup (home_dir);
433 0 : if (!new_home_dir)
434 : {
435 0 : free (new_file_name);
436 0 : return gpg_error_from_syserror ();
437 : }
438 : }
439 : else
440 : {
441 80 : const char *ohome_dir = engine_get_home_dir (proto);
442 80 : if (ohome_dir)
443 : {
444 0 : new_home_dir = strdup (ohome_dir);
445 0 : if (!new_home_dir)
446 : {
447 0 : free (new_file_name);
448 0 : return gpg_error_from_syserror ();
449 : }
450 : }
451 : else
452 80 : new_home_dir = NULL;
453 : }
454 :
455 80 : new_version = engine_get_version (proto, new_file_name);
456 80 : if (!new_version)
457 : {
458 0 : new_version = strdup ("1.0.0"); /* Fake one for dummy entries. */
459 0 : if (!new_version)
460 : {
461 0 : free (new_file_name);
462 0 : free (new_home_dir);
463 : }
464 : }
465 :
466 : /* Remove the old members. */
467 80 : assert (info->file_name);
468 80 : free (info->file_name);
469 80 : if (info->home_dir)
470 0 : free (info->home_dir);
471 80 : if (info->version)
472 80 : free (info->version);
473 :
474 : /* Install the new members. */
475 80 : info->file_name = new_file_name;
476 80 : info->home_dir = new_home_dir;
477 80 : info->version = new_version;
478 :
479 80 : return 0;
480 : }
481 :
482 :
483 : /* Set the default engine info for the protocol PROTO to the file name
484 : FILE_NAME and the home directory HOME_DIR. */
485 : gpgme_error_t
486 0 : gpgme_set_engine_info (gpgme_protocol_t proto,
487 : const char *file_name, const char *home_dir)
488 : {
489 : gpgme_error_t err;
490 : gpgme_engine_info_t info;
491 :
492 0 : LOCK (engine_info_lock);
493 0 : info = engine_info;
494 0 : if (!info)
495 : {
496 : /* Make sure it is initialized. */
497 0 : UNLOCK (engine_info_lock);
498 0 : err = gpgme_get_engine_info (&info);
499 0 : if (err)
500 0 : return err;
501 :
502 0 : LOCK (engine_info_lock);
503 : }
504 :
505 0 : err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
506 0 : UNLOCK (engine_info_lock);
507 0 : return err;
508 : }
509 :
510 :
511 : gpgme_error_t
512 275 : _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
513 : {
514 : engine_t engine;
515 :
516 275 : if (!info->file_name || !info->version)
517 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
518 :
519 275 : engine = calloc (1, sizeof *engine);
520 275 : if (!engine)
521 0 : return gpg_error_from_syserror ();
522 :
523 275 : engine->ops = engine_ops[info->protocol];
524 275 : if (engine->ops->new)
525 : {
526 : gpgme_error_t err;
527 550 : err = (*engine->ops->new) (&engine->engine,
528 275 : info->file_name, info->home_dir,
529 275 : info->version);
530 275 : if (err)
531 : {
532 0 : free (engine);
533 0 : return err;
534 : }
535 : }
536 : else
537 0 : engine->engine = NULL;
538 :
539 275 : *r_engine = engine;
540 275 : return 0;
541 : }
542 :
543 :
544 : gpgme_error_t
545 60 : _gpgme_engine_reset (engine_t engine)
546 : {
547 60 : if (!engine)
548 0 : return gpg_error (GPG_ERR_INV_VALUE);
549 :
550 60 : if (!engine->ops->reset)
551 56 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
552 :
553 4 : return (*engine->ops->reset) (engine->engine);
554 : }
555 :
556 :
557 : void
558 278 : _gpgme_engine_release (engine_t engine)
559 : {
560 278 : if (!engine)
561 285 : return;
562 :
563 271 : if (engine->ops->release)
564 271 : (*engine->ops->release) (engine->engine);
565 271 : free (engine);
566 : }
567 :
568 :
569 : /* Set a status callback which is used to monitor the status values
570 : * before they are passed to a handler set with
571 : * _gpgme_engine_set_status_handler. */
572 : void
573 2 : _gpgme_engine_set_status_cb (engine_t engine,
574 : gpgme_status_cb_t cb, void *cb_value)
575 : {
576 2 : if (!engine)
577 2 : return;
578 :
579 2 : if (engine->ops->set_status_cb)
580 2 : (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
581 : }
582 :
583 :
584 : void
585 302 : _gpgme_engine_set_status_handler (engine_t engine,
586 : engine_status_handler_t fnc, void *fnc_value)
587 : {
588 302 : if (!engine)
589 302 : return;
590 :
591 302 : if (engine->ops->set_status_handler)
592 302 : (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
593 : }
594 :
595 :
596 : gpgme_error_t
597 63 : _gpgme_engine_set_command_handler (engine_t engine,
598 : engine_command_handler_t fnc,
599 : void *fnc_value,
600 : gpgme_data_t linked_data)
601 : {
602 63 : if (!engine)
603 0 : return gpg_error (GPG_ERR_INV_VALUE);
604 :
605 63 : if (!engine->ops->set_command_handler)
606 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
607 :
608 63 : return (*engine->ops->set_command_handler) (engine->engine,
609 : fnc, fnc_value, linked_data);
610 : }
611 :
612 : gpgme_error_t
613 102 : _gpgme_engine_set_colon_line_handler (engine_t engine,
614 : engine_colon_line_handler_t fnc,
615 : void *fnc_value)
616 : {
617 102 : if (!engine)
618 0 : return gpg_error (GPG_ERR_INV_VALUE);
619 :
620 102 : if (!engine->ops->set_colon_line_handler)
621 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
622 :
623 102 : return (*engine->ops->set_colon_line_handler) (engine->engine,
624 : fnc, fnc_value);
625 : }
626 :
627 : gpgme_error_t
628 558 : _gpgme_engine_set_locale (engine_t engine, int category,
629 : const char *value)
630 : {
631 558 : if (!engine)
632 0 : return gpg_error (GPG_ERR_INV_VALUE);
633 :
634 558 : if (!engine->ops->set_locale)
635 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
636 :
637 558 : return (*engine->ops->set_locale) (engine->engine, category, value);
638 : }
639 :
640 :
641 : gpgme_error_t
642 0 : _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
643 : {
644 0 : if (!engine)
645 0 : return gpg_error (GPG_ERR_INV_VALUE);
646 :
647 0 : if (!engine->ops->set_protocol)
648 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
649 :
650 0 : return (*engine->ops->set_protocol) (engine->engine, protocol);
651 : }
652 :
653 :
654 : gpgme_error_t
655 29 : _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
656 : gpgme_data_t plain)
657 : {
658 29 : if (!engine)
659 0 : return gpg_error (GPG_ERR_INV_VALUE);
660 :
661 29 : if (!engine->ops->decrypt)
662 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
663 :
664 29 : return (*engine->ops->decrypt) (engine->engine, ciph, plain);
665 : }
666 :
667 :
668 : gpgme_error_t
669 7 : _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
670 : gpgme_data_t plain)
671 : {
672 7 : if (!engine)
673 0 : return gpg_error (GPG_ERR_INV_VALUE);
674 :
675 7 : if (!engine->ops->decrypt_verify)
676 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
677 :
678 7 : return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain);
679 : }
680 :
681 :
682 : gpgme_error_t
683 0 : _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
684 : int allow_secret)
685 : {
686 0 : if (!engine)
687 0 : return gpg_error (GPG_ERR_INV_VALUE);
688 :
689 0 : if (!engine->ops->delete)
690 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
691 :
692 0 : return (*engine->ops->delete) (engine->engine, key, allow_secret);
693 : }
694 :
695 :
696 : gpgme_error_t
697 7 : _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
698 : gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
699 : {
700 7 : if (!engine)
701 0 : return gpg_error (GPG_ERR_INV_VALUE);
702 :
703 7 : if (!engine->ops->edit)
704 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
705 :
706 7 : return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
707 : }
708 :
709 :
710 : gpgme_error_t
711 47 : _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
712 : gpgme_encrypt_flags_t flags,
713 : gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
714 : {
715 47 : if (!engine)
716 0 : return gpg_error (GPG_ERR_INV_VALUE);
717 :
718 47 : if (!engine->ops->encrypt)
719 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
720 :
721 47 : return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
722 : use_armor);
723 : }
724 :
725 :
726 : gpgme_error_t
727 7 : _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
728 : gpgme_encrypt_flags_t flags,
729 : gpgme_data_t plain, gpgme_data_t ciph,
730 : int use_armor, gpgme_ctx_t ctx /* FIXME */)
731 : {
732 7 : if (!engine)
733 0 : return gpg_error (GPG_ERR_INV_VALUE);
734 :
735 7 : if (!engine->ops->encrypt_sign)
736 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
737 :
738 7 : return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
739 : plain, ciph, use_armor, ctx);
740 : }
741 :
742 :
743 : gpgme_error_t
744 0 : _gpgme_engine_op_export (engine_t engine, const char *pattern,
745 : gpgme_export_mode_t mode, gpgme_data_t keydata,
746 : int use_armor)
747 : {
748 0 : if (!engine)
749 0 : return gpg_error (GPG_ERR_INV_VALUE);
750 :
751 0 : if (!engine->ops->export)
752 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
753 :
754 0 : return (*engine->ops->export) (engine->engine, pattern, mode,
755 : keydata, use_armor);
756 : }
757 :
758 :
759 : gpgme_error_t
760 6 : _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
761 : unsigned int reserved, gpgme_data_t keydata,
762 : int use_armor)
763 : {
764 6 : if (!engine)
765 0 : return gpg_error (GPG_ERR_INV_VALUE);
766 :
767 6 : if (!engine->ops->export_ext)
768 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
769 :
770 6 : return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
771 : keydata, use_armor);
772 : }
773 :
774 :
775 : gpgme_error_t
776 2 : _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
777 : int use_armor, gpgme_data_t pubkey,
778 : gpgme_data_t seckey)
779 : {
780 2 : if (!engine)
781 0 : return gpg_error (GPG_ERR_INV_VALUE);
782 :
783 2 : if (!engine->ops->genkey)
784 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
785 :
786 2 : return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
787 : pubkey, seckey);
788 : }
789 :
790 :
791 : gpgme_error_t
792 8 : _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
793 : gpgme_key_t *keyarray)
794 : {
795 8 : if (!engine)
796 0 : return gpg_error (GPG_ERR_INV_VALUE);
797 :
798 8 : if (!engine->ops->import)
799 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
800 :
801 8 : return (*engine->ops->import) (engine->engine, keydata, keyarray);
802 : }
803 :
804 :
805 : gpgme_error_t
806 99 : _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
807 : int secret_only, gpgme_keylist_mode_t mode,
808 : int engine_flags)
809 : {
810 99 : if (!engine)
811 0 : return gpg_error (GPG_ERR_INV_VALUE);
812 :
813 99 : if (!engine->ops->keylist)
814 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
815 :
816 99 : return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
817 : engine_flags);
818 : }
819 :
820 :
821 : gpgme_error_t
822 0 : _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
823 : int secret_only, int reserved,
824 : gpgme_keylist_mode_t mode, int engine_flags)
825 : {
826 0 : if (!engine)
827 0 : return gpg_error (GPG_ERR_INV_VALUE);
828 :
829 0 : if (!engine->ops->keylist_ext)
830 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
831 :
832 0 : return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
833 : reserved, mode, engine_flags);
834 : }
835 :
836 :
837 : gpgme_error_t
838 32 : _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
839 : gpgme_sig_mode_t mode, int use_armor,
840 : int use_textmode, int include_certs,
841 : gpgme_ctx_t ctx /* FIXME */)
842 : {
843 32 : if (!engine)
844 0 : return gpg_error (GPG_ERR_INV_VALUE);
845 :
846 32 : if (!engine->ops->sign)
847 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
848 :
849 32 : return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
850 : use_textmode, include_certs, ctx);
851 : }
852 :
853 :
854 : gpgme_error_t
855 3 : _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
856 : {
857 3 : if (!engine)
858 0 : return gpg_error (GPG_ERR_INV_VALUE);
859 :
860 3 : if (!engine->ops->trustlist)
861 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
862 :
863 3 : return (*engine->ops->trustlist) (engine->engine, pattern);
864 : }
865 :
866 :
867 : gpgme_error_t
868 31 : _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
869 : gpgme_data_t signed_text, gpgme_data_t plaintext)
870 : {
871 31 : if (!engine)
872 0 : return gpg_error (GPG_ERR_INV_VALUE);
873 :
874 31 : if (!engine->ops->verify)
875 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
876 :
877 31 : return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
878 : }
879 :
880 :
881 : gpgme_error_t
882 24 : _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
883 : unsigned int flags)
884 : {
885 24 : if (!engine)
886 0 : return gpg_error (GPG_ERR_INV_VALUE);
887 :
888 24 : if (!engine->ops->getauditlog)
889 22 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
890 :
891 2 : return (*engine->ops->getauditlog) (engine->engine, output, flags);
892 : }
893 :
894 :
895 : gpgme_error_t
896 8 : _gpgme_engine_op_assuan_transact (engine_t engine,
897 : const char *command,
898 : gpgme_assuan_data_cb_t data_cb,
899 : void *data_cb_value,
900 : gpgme_assuan_inquire_cb_t inq_cb,
901 : void *inq_cb_value,
902 : gpgme_assuan_status_cb_t status_cb,
903 : void *status_cb_value)
904 : {
905 8 : if (!engine)
906 0 : return gpg_error (GPG_ERR_INV_VALUE);
907 :
908 8 : if (!engine->ops->opassuan_transact)
909 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
910 :
911 8 : return (*engine->ops->opassuan_transact) (engine->engine,
912 : command,
913 : data_cb, data_cb_value,
914 : inq_cb, inq_cb_value,
915 : status_cb, status_cb_value);
916 : }
917 :
918 :
919 : gpgme_error_t
920 0 : _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
921 : {
922 0 : if (!engine)
923 0 : return gpg_error (GPG_ERR_INV_VALUE);
924 :
925 0 : if (!engine->ops->conf_load)
926 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
927 :
928 0 : return (*engine->ops->conf_load) (engine->engine, conf_p);
929 : }
930 :
931 :
932 : gpgme_error_t
933 0 : _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
934 : {
935 0 : if (!engine)
936 0 : return gpg_error (GPG_ERR_INV_VALUE);
937 :
938 0 : if (!engine->ops->conf_save)
939 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
940 :
941 0 : return (*engine->ops->conf_save) (engine->engine, conf);
942 : }
943 :
944 :
945 : void
946 310 : _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
947 : {
948 310 : if (!engine)
949 310 : return;
950 :
951 310 : (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
952 : }
953 :
954 :
955 : void
956 566 : _gpgme_engine_io_event (engine_t engine,
957 : gpgme_event_io_t type, void *type_data)
958 : {
959 566 : if (!engine)
960 566 : return;
961 :
962 566 : (*engine->ops->io_event) (engine->engine, type, type_data);
963 : }
964 :
965 :
966 : /* Cancel the session and the pending operation if any. */
967 : gpgme_error_t
968 13 : _gpgme_engine_cancel (engine_t engine)
969 : {
970 13 : if (!engine)
971 0 : return gpg_error (GPG_ERR_INV_VALUE);
972 :
973 13 : if (!engine->ops->cancel)
974 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
975 :
976 13 : return (*engine->ops->cancel) (engine->engine);
977 : }
978 :
979 :
980 : /* Cancel the pending operation, but not the complete session. */
981 : gpgme_error_t
982 1 : _gpgme_engine_cancel_op (engine_t engine)
983 : {
984 1 : if (!engine)
985 0 : return gpg_error (GPG_ERR_INV_VALUE);
986 :
987 1 : if (!engine->ops->cancel_op)
988 0 : return 0;
989 :
990 1 : return (*engine->ops->cancel_op) (engine->engine);
991 : }
992 :
993 :
994 : /* Change the passphrase for KEY. */
995 : gpgme_error_t
996 0 : _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
997 : unsigned int flags)
998 : {
999 0 : if (!engine)
1000 0 : return gpg_error (GPG_ERR_INV_VALUE);
1001 :
1002 0 : if (!engine->ops->passwd)
1003 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1004 :
1005 0 : return (*engine->ops->passwd) (engine->engine, key, flags);
1006 : }
1007 :
1008 :
1009 : /* Set the pinentry mode for ENGINE to MODE. */
1010 : gpgme_error_t
1011 279 : _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1012 : {
1013 279 : if (!engine)
1014 0 : return gpg_error (GPG_ERR_INV_VALUE);
1015 :
1016 279 : if (!engine->ops->set_pinentry_mode)
1017 13 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1018 :
1019 266 : return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1020 : }
1021 :
1022 :
1023 : gpgme_error_t
1024 0 : _gpgme_engine_op_spawn (engine_t engine,
1025 : const char *file, const char *argv[],
1026 : gpgme_data_t datain,
1027 : gpgme_data_t dataout, gpgme_data_t dataerr,
1028 : unsigned int flags)
1029 : {
1030 0 : if (!engine)
1031 0 : return gpg_error (GPG_ERR_INV_VALUE);
1032 :
1033 0 : if (!engine->ops->opspawn)
1034 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1035 :
1036 0 : return (*engine->ops->opspawn) (engine->engine, file, argv,
1037 : datain, dataout, dataerr, flags);
1038 : }
|