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 <https://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 553 : engine_get_file_name (gpgme_protocol_t proto)
74 : {
75 553 : if (proto > DIM (engine_ops))
76 0 : return NULL;
77 :
78 553 : if (engine_ops[proto] && engine_ops[proto]->get_file_name)
79 553 : 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 669 : engine_get_home_dir (gpgme_protocol_t proto)
88 : {
89 669 : if (proto > DIM (engine_ops))
90 0 : return NULL;
91 :
92 669 : if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
93 79 : return (*engine_ops[proto]->get_home_dir) ();
94 : else
95 590 : 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 669 : engine_get_version (gpgme_protocol_t proto, const char *file_name)
104 : {
105 669 : if (proto > DIM (engine_ops))
106 0 : return NULL;
107 :
108 669 : if (engine_ops[proto] && engine_ops[proto]->get_version)
109 669 : 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 474 : engine_get_req_version (gpgme_protocol_t proto)
119 : {
120 474 : if (proto > DIM (engine_ops))
121 0 : return NULL;
122 :
123 474 : if (engine_ops[proto] && engine_ops[proto]->get_req_version)
124 474 : 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 184 : 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 184 : LOCK (engine_info_lock);
139 184 : info = engine_info;
140 184 : if (!info)
141 : {
142 : /* Make sure it is initialized. */
143 72 : UNLOCK (engine_info_lock);
144 72 : err = gpgme_get_engine_info (&info);
145 72 : if (err)
146 0 : return err;
147 :
148 72 : LOCK (engine_info_lock);
149 : }
150 :
151 381 : while (info && info->protocol != proto)
152 13 : info = info->next;
153 :
154 184 : if (!info)
155 0 : result = 0;
156 : else
157 184 : result = _gpgme_compare_versions (info->version,
158 184 : info->req_version);
159 :
160 184 : UNLOCK (engine_info_lock);
161 184 : return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
162 : }
163 :
164 :
165 : /* Release the engine info INFO. */
166 : void
167 520 : _gpgme_engine_info_release (gpgme_engine_info_t info)
168 : {
169 4160 : while (info)
170 : {
171 3120 : gpgme_engine_info_t next_info = info->next;
172 :
173 3120 : if (info->file_name)
174 3117 : free (info->file_name);
175 3120 : if (info->home_dir)
176 520 : free (info->home_dir);
177 3120 : if (info->version)
178 3118 : free (info->version);
179 3120 : free (info);
180 3120 : info = next_info;
181 : }
182 520 : }
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 86 : gpgme_get_engine_info (gpgme_engine_info_t *info)
211 : {
212 : gpgme_error_t err;
213 :
214 86 : LOCK (engine_info_lock);
215 86 : if (!engine_info)
216 : {
217 79 : gpgme_engine_info_t *lastp = &engine_info;
218 79 : 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 79 : err = 0;
228 632 : for (proto = 0; proto < DIM (proto_list); proto++)
229 : {
230 553 : const char *ofile_name = engine_get_file_name (proto_list[proto]);
231 553 : const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
232 553 : char *version = engine_get_version (proto_list[proto], NULL);
233 : char *file_name;
234 : char *home_dir;
235 :
236 553 : if (!ofile_name)
237 79 : continue;
238 :
239 474 : file_name = strdup (ofile_name);
240 474 : if (!file_name)
241 0 : err = gpg_error_from_syserror ();
242 :
243 474 : if (ohome_dir)
244 : {
245 79 : home_dir = strdup (ohome_dir);
246 79 : if (!home_dir && !err)
247 0 : err = gpg_error_from_syserror ();
248 : }
249 : else
250 395 : home_dir = NULL;
251 :
252 474 : *lastp = calloc (1, sizeof (*engine_info));
253 474 : if (!*lastp && !err)
254 0 : err = gpg_error_from_syserror ();
255 :
256 : /* Check against the optional minimal engine version. */
257 474 : 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 474 : if (!err && !version)
269 : {
270 237 : version = strdup ("1.0.0");
271 237 : if (!version)
272 0 : err = gpg_error_from_syserror ();
273 : }
274 :
275 474 : 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 474 : (*lastp)->protocol = proto_list[proto];
292 474 : (*lastp)->file_name = file_name;
293 474 : (*lastp)->home_dir = home_dir;
294 474 : (*lastp)->version = version;
295 474 : (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
296 474 : if (!(*lastp)->req_version)
297 237 : (*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
298 474 : (*lastp)->next = NULL;
299 474 : lastp = &(*lastp)->next;
300 : }
301 : }
302 :
303 86 : *info = engine_info;
304 86 : UNLOCK (engine_info_lock);
305 86 : return 0;
306 : }
307 :
308 :
309 : /* Get a deep copy of the engine info and return it in INFO. */
310 : gpgme_error_t
311 432 : _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
312 : {
313 432 : 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 432 : LOCK (engine_info_lock);
319 437 : info = engine_info;
320 437 : if (!info)
321 : {
322 : /* Make sure it is initialized. */
323 4 : UNLOCK (engine_info_lock);
324 4 : err = gpgme_get_engine_info (&info);
325 4 : if (err)
326 0 : return err;
327 :
328 4 : LOCK (engine_info_lock);
329 : }
330 :
331 437 : new_info = NULL;
332 437 : lastp = &new_info;
333 :
334 3499 : while (info)
335 : {
336 : char *file_name;
337 : char *home_dir;
338 : char *version;
339 :
340 2624 : assert (info->file_name);
341 2625 : file_name = strdup (info->file_name);
342 2625 : if (!file_name)
343 0 : err = gpg_error_from_syserror ();
344 :
345 2625 : if (info->home_dir)
346 : {
347 438 : home_dir = strdup (info->home_dir);
348 438 : if (!home_dir && !err)
349 0 : err = gpg_error_from_syserror ();
350 : }
351 : else
352 2187 : home_dir = NULL;
353 :
354 2625 : if (info->version)
355 : {
356 2625 : version = strdup (info->version);
357 2625 : if (!version && !err)
358 0 : err = gpg_error_from_syserror ();
359 : }
360 : else
361 0 : version = NULL;
362 :
363 2625 : *lastp = malloc (sizeof (*engine_info));
364 2625 : if (!*lastp && !err)
365 0 : err = gpg_error_from_syserror ();
366 :
367 2625 : 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 2625 : (*lastp)->protocol = info->protocol;
382 2625 : (*lastp)->file_name = file_name;
383 2625 : (*lastp)->home_dir = home_dir;
384 2625 : (*lastp)->version = version;
385 2625 : (*lastp)->req_version = info->req_version;
386 2625 : (*lastp)->next = NULL;
387 2625 : lastp = &(*lastp)->next;
388 :
389 2625 : info = info->next;
390 : }
391 :
392 438 : *r_info = new_info;
393 438 : UNLOCK (engine_info_lock);
394 438 : 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 116 : _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 116 : if (proto > DIM (engine_ops))
410 0 : return gpg_error (GPG_ERR_INV_VALUE);
411 :
412 233 : while (info && info->protocol != proto)
413 1 : info = info->next;
414 :
415 116 : if (!info)
416 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
417 :
418 : /* Prepare new members. */
419 116 : if (file_name)
420 116 : 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 116 : if (!new_file_name)
428 0 : return gpg_error_from_syserror ();
429 :
430 116 : 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 116 : const char *ohome_dir = engine_get_home_dir (proto);
442 116 : 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 116 : new_home_dir = NULL;
453 : }
454 :
455 116 : new_version = engine_get_version (proto, new_file_name);
456 117 : 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 117 : assert (info->file_name);
468 117 : free (info->file_name);
469 117 : if (info->home_dir)
470 0 : free (info->home_dir);
471 117 : if (info->version)
472 117 : free (info->version);
473 :
474 : /* Install the new members. */
475 117 : info->file_name = new_file_name;
476 117 : info->home_dir = new_home_dir;
477 117 : info->version = new_version;
478 :
479 117 : 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 526 : _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
513 : {
514 : engine_t engine;
515 :
516 526 : if (!info->file_name || !info->version)
517 0 : return trace_gpg_error (GPG_ERR_INV_ENGINE);
518 :
519 526 : engine = calloc (1, sizeof *engine);
520 526 : if (!engine)
521 0 : return gpg_error_from_syserror ();
522 :
523 526 : engine->ops = engine_ops[info->protocol];
524 526 : if (engine->ops->new)
525 : {
526 : gpgme_error_t err;
527 1052 : err = (*engine->ops->new) (&engine->engine,
528 526 : info->file_name, info->home_dir,
529 526 : info->version);
530 523 : if (err)
531 : {
532 0 : free (engine);
533 0 : return err;
534 : }
535 : }
536 : else
537 0 : engine->engine = NULL;
538 :
539 523 : *r_engine = engine;
540 523 : return 0;
541 : }
542 :
543 :
544 : gpgme_error_t
545 104 : _gpgme_engine_reset (engine_t engine)
546 : {
547 104 : if (!engine)
548 0 : return gpg_error (GPG_ERR_INV_VALUE);
549 :
550 104 : if (!engine->ops->reset)
551 100 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
552 :
553 4 : return (*engine->ops->reset) (engine->engine);
554 : }
555 :
556 :
557 : void
558 618 : _gpgme_engine_release (engine_t engine)
559 : {
560 618 : if (!engine)
561 632 : return;
562 :
563 606 : if (engine->ops->release)
564 607 : (*engine->ops->release) (engine->engine);
565 608 : 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 4 : _gpgme_engine_set_status_cb (engine_t engine,
574 : gpgme_status_cb_t cb, void *cb_value)
575 : {
576 4 : if (!engine)
577 4 : return;
578 :
579 4 : if (engine->ops->set_status_cb)
580 4 : (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
581 : }
582 :
583 :
584 : void
585 549 : _gpgme_engine_set_status_handler (engine_t engine,
586 : engine_status_handler_t fnc, void *fnc_value)
587 : {
588 549 : if (!engine)
589 548 : return;
590 :
591 549 : if (engine->ops->set_status_handler)
592 551 : (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
593 : }
594 :
595 :
596 : gpgme_error_t
597 84 : _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 84 : if (!engine)
603 0 : return gpg_error (GPG_ERR_INV_VALUE);
604 :
605 84 : if (!engine->ops->set_command_handler)
606 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
607 :
608 84 : return (*engine->ops->set_command_handler) (engine->engine,
609 : fnc, fnc_value, linked_data);
610 : }
611 :
612 : gpgme_error_t
613 230 : _gpgme_engine_set_colon_line_handler (engine_t engine,
614 : engine_colon_line_handler_t fnc,
615 : void *fnc_value)
616 : {
617 230 : if (!engine)
618 0 : return gpg_error (GPG_ERR_INV_VALUE);
619 :
620 230 : if (!engine->ops->set_colon_line_handler)
621 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
622 :
623 230 : return (*engine->ops->set_colon_line_handler) (engine->engine,
624 : fnc, fnc_value);
625 : }
626 :
627 : gpgme_error_t
628 1054 : _gpgme_engine_set_locale (engine_t engine, int category,
629 : const char *value)
630 : {
631 1054 : if (!engine)
632 0 : return gpg_error (GPG_ERR_INV_VALUE);
633 :
634 1054 : if (!engine->ops->set_locale)
635 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
636 :
637 1054 : 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 35 : _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
656 : gpgme_data_t plain, int export_session_key,
657 : const char *override_session_key)
658 : {
659 35 : if (!engine)
660 0 : return gpg_error (GPG_ERR_INV_VALUE);
661 :
662 35 : if (!engine->ops->decrypt)
663 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
664 :
665 35 : return (*engine->ops->decrypt) (engine->engine, ciph, plain,
666 : export_session_key, override_session_key);
667 : }
668 :
669 :
670 : gpgme_error_t
671 13 : _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
672 : gpgme_data_t plain, int export_session_key,
673 : const char *override_session_key)
674 : {
675 13 : if (!engine)
676 0 : return gpg_error (GPG_ERR_INV_VALUE);
677 :
678 13 : if (!engine->ops->decrypt_verify)
679 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
680 :
681 13 : return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain,
682 : export_session_key,
683 : override_session_key);
684 : }
685 :
686 :
687 : gpgme_error_t
688 0 : _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
689 : int allow_secret)
690 : {
691 0 : if (!engine)
692 0 : return gpg_error (GPG_ERR_INV_VALUE);
693 :
694 0 : if (!engine->ops->delete)
695 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
696 :
697 0 : return (*engine->ops->delete) (engine->engine, key, allow_secret);
698 : }
699 :
700 :
701 : gpgme_error_t
702 13 : _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
703 : gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
704 : {
705 13 : if (!engine)
706 0 : return gpg_error (GPG_ERR_INV_VALUE);
707 :
708 13 : if (!engine->ops->edit)
709 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
710 :
711 13 : return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
712 : }
713 :
714 :
715 : gpgme_error_t
716 64 : _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
717 : gpgme_encrypt_flags_t flags,
718 : gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
719 : {
720 64 : if (!engine)
721 0 : return gpg_error (GPG_ERR_INV_VALUE);
722 :
723 64 : if (!engine->ops->encrypt)
724 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
725 :
726 64 : return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
727 : use_armor);
728 : }
729 :
730 :
731 : gpgme_error_t
732 12 : _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
733 : gpgme_encrypt_flags_t flags,
734 : gpgme_data_t plain, gpgme_data_t ciph,
735 : int use_armor, gpgme_ctx_t ctx /* FIXME */)
736 : {
737 12 : if (!engine)
738 0 : return gpg_error (GPG_ERR_INV_VALUE);
739 :
740 12 : if (!engine->ops->encrypt_sign)
741 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
742 :
743 12 : return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
744 : plain, ciph, use_armor, ctx);
745 : }
746 :
747 :
748 : gpgme_error_t
749 0 : _gpgme_engine_op_export (engine_t engine, const char *pattern,
750 : gpgme_export_mode_t mode, gpgme_data_t keydata,
751 : int use_armor)
752 : {
753 0 : if (!engine)
754 0 : return gpg_error (GPG_ERR_INV_VALUE);
755 :
756 0 : if (!engine->ops->export)
757 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
758 :
759 0 : return (*engine->ops->export) (engine->engine, pattern, mode,
760 : keydata, use_armor);
761 : }
762 :
763 :
764 : gpgme_error_t
765 8 : _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
766 : unsigned int reserved, gpgme_data_t keydata,
767 : int use_armor)
768 : {
769 8 : if (!engine)
770 0 : return gpg_error (GPG_ERR_INV_VALUE);
771 :
772 8 : if (!engine->ops->export_ext)
773 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
774 :
775 8 : return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
776 : keydata, use_armor);
777 : }
778 :
779 :
780 : gpgme_error_t
781 4 : _gpgme_engine_op_genkey (engine_t engine,
782 : const char *userid, const char *algo,
783 : unsigned long reserved, unsigned long expires,
784 : gpgme_key_t key, unsigned int flags,
785 : gpgme_data_t help_data,
786 : unsigned int extraflags,
787 : gpgme_data_t pubkey, gpgme_data_t seckey)
788 : {
789 4 : if (!engine)
790 0 : return gpg_error (GPG_ERR_INV_VALUE);
791 :
792 4 : if (!engine->ops->genkey)
793 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
794 :
795 4 : return (*engine->ops->genkey) (engine->engine,
796 : userid, algo, reserved, expires, key, flags,
797 : help_data, extraflags,
798 : pubkey, seckey);
799 : }
800 :
801 :
802 : gpgme_error_t
803 0 : _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
804 : unsigned long expires, unsigned int flags,
805 : gpgme_ctx_t ctx)
806 : {
807 0 : if (!engine)
808 0 : return gpg_error (GPG_ERR_INV_VALUE);
809 :
810 0 : if (!engine->ops->keysign)
811 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
812 :
813 0 : return (*engine->ops->keysign) (engine->engine,
814 : key, userid, expires, flags, ctx);
815 : }
816 :
817 :
818 : gpgme_error_t
819 2 : _gpgme_engine_op_tofu_policy (engine_t engine,
820 : gpgme_key_t key, gpgme_tofu_policy_t policy)
821 : {
822 2 : if (!engine)
823 0 : return gpg_error (GPG_ERR_INV_VALUE);
824 :
825 2 : if (!engine->ops->tofu_policy)
826 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
827 :
828 2 : return (*engine->ops->tofu_policy) (engine->engine, key, policy);
829 : }
830 :
831 :
832 : gpgme_error_t
833 12 : _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
834 : gpgme_key_t *keyarray)
835 : {
836 12 : if (!engine)
837 0 : return gpg_error (GPG_ERR_INV_VALUE);
838 :
839 12 : if (!engine->ops->import)
840 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
841 :
842 12 : return (*engine->ops->import) (engine->engine, keydata, keyarray);
843 : }
844 :
845 :
846 : gpgme_error_t
847 228 : _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
848 : int secret_only, gpgme_keylist_mode_t mode,
849 : int engine_flags)
850 : {
851 228 : if (!engine)
852 0 : return gpg_error (GPG_ERR_INV_VALUE);
853 :
854 228 : if (!engine->ops->keylist)
855 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
856 :
857 228 : return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
858 : engine_flags);
859 : }
860 :
861 :
862 : gpgme_error_t
863 0 : _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
864 : int secret_only, int reserved,
865 : gpgme_keylist_mode_t mode, int engine_flags)
866 : {
867 0 : if (!engine)
868 0 : return gpg_error (GPG_ERR_INV_VALUE);
869 :
870 0 : if (!engine->ops->keylist_ext)
871 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
872 :
873 0 : return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
874 : reserved, mode, engine_flags);
875 : }
876 :
877 :
878 : gpgme_error_t
879 48 : _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
880 : gpgme_sig_mode_t mode, int use_armor,
881 : int use_textmode, int include_certs,
882 : gpgme_ctx_t ctx /* FIXME */)
883 : {
884 48 : if (!engine)
885 0 : return gpg_error (GPG_ERR_INV_VALUE);
886 :
887 48 : if (!engine->ops->sign)
888 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
889 :
890 48 : return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
891 : use_textmode, include_certs, ctx);
892 : }
893 :
894 :
895 : gpgme_error_t
896 5 : _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
897 : {
898 5 : if (!engine)
899 0 : return gpg_error (GPG_ERR_INV_VALUE);
900 :
901 5 : if (!engine->ops->trustlist)
902 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
903 :
904 5 : return (*engine->ops->trustlist) (engine->engine, pattern);
905 : }
906 :
907 :
908 : gpgme_error_t
909 84 : _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
910 : gpgme_data_t signed_text, gpgme_data_t plaintext,
911 : gpgme_ctx_t ctx)
912 : {
913 84 : if (!engine)
914 0 : return gpg_error (GPG_ERR_INV_VALUE);
915 :
916 84 : if (!engine->ops->verify)
917 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
918 :
919 84 : return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
920 : ctx);
921 : }
922 :
923 :
924 : gpgme_error_t
925 25 : _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
926 : unsigned int flags)
927 : {
928 25 : if (!engine)
929 0 : return gpg_error (GPG_ERR_INV_VALUE);
930 :
931 25 : if (!engine->ops->getauditlog)
932 23 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
933 :
934 2 : return (*engine->ops->getauditlog) (engine->engine, output, flags);
935 : }
936 :
937 :
938 : gpgme_error_t
939 16 : _gpgme_engine_op_assuan_transact (engine_t engine,
940 : const char *command,
941 : gpgme_assuan_data_cb_t data_cb,
942 : void *data_cb_value,
943 : gpgme_assuan_inquire_cb_t inq_cb,
944 : void *inq_cb_value,
945 : gpgme_assuan_status_cb_t status_cb,
946 : void *status_cb_value)
947 : {
948 16 : if (!engine)
949 0 : return gpg_error (GPG_ERR_INV_VALUE);
950 :
951 16 : if (!engine->ops->opassuan_transact)
952 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
953 :
954 16 : return (*engine->ops->opassuan_transact) (engine->engine,
955 : command,
956 : data_cb, data_cb_value,
957 : inq_cb, inq_cb_value,
958 : status_cb, status_cb_value);
959 : }
960 :
961 :
962 : gpgme_error_t
963 0 : _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
964 : {
965 0 : if (!engine)
966 0 : return gpg_error (GPG_ERR_INV_VALUE);
967 :
968 0 : if (!engine->ops->conf_load)
969 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
970 :
971 0 : return (*engine->ops->conf_load) (engine->engine, conf_p);
972 : }
973 :
974 :
975 : gpgme_error_t
976 0 : _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
977 : {
978 0 : if (!engine)
979 0 : return gpg_error (GPG_ERR_INV_VALUE);
980 :
981 0 : if (!engine->ops->conf_save)
982 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
983 :
984 0 : return (*engine->ops->conf_save) (engine->engine, conf);
985 : }
986 :
987 :
988 : gpgme_error_t
989 0 : _gpgme_engine_op_query_swdb (engine_t engine,
990 : const char *name, const char *iversion,
991 : gpgme_query_swdb_result_t result)
992 : {
993 0 : if (!engine)
994 0 : return gpg_error (GPG_ERR_INV_VALUE);
995 :
996 0 : if (!engine->ops->query_swdb)
997 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
998 :
999 0 : return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
1000 : }
1001 :
1002 :
1003 : void
1004 565 : _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
1005 : {
1006 565 : if (!engine)
1007 564 : return;
1008 :
1009 565 : (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
1010 : }
1011 :
1012 :
1013 : void
1014 4308 : _gpgme_engine_io_event (engine_t engine,
1015 : gpgme_event_io_t type, void *type_data)
1016 : {
1017 4308 : if (!engine)
1018 2073 : return;
1019 :
1020 4308 : (*engine->ops->io_event) (engine->engine, type, type_data);
1021 : }
1022 :
1023 :
1024 : /* Cancel the session and the pending operation if any. */
1025 : gpgme_error_t
1026 24 : _gpgme_engine_cancel (engine_t engine)
1027 : {
1028 24 : if (!engine)
1029 0 : return gpg_error (GPG_ERR_INV_VALUE);
1030 :
1031 24 : if (!engine->ops->cancel)
1032 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1033 :
1034 24 : return (*engine->ops->cancel) (engine->engine);
1035 : }
1036 :
1037 :
1038 : /* Cancel the pending operation, but not the complete session. */
1039 : gpgme_error_t
1040 4 : _gpgme_engine_cancel_op (engine_t engine)
1041 : {
1042 4 : if (!engine)
1043 0 : return gpg_error (GPG_ERR_INV_VALUE);
1044 :
1045 4 : if (!engine->ops->cancel_op)
1046 0 : return 0;
1047 :
1048 4 : return (*engine->ops->cancel_op) (engine->engine);
1049 : }
1050 :
1051 :
1052 : /* Change the passphrase for KEY. */
1053 : gpgme_error_t
1054 0 : _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
1055 : unsigned int flags)
1056 : {
1057 0 : if (!engine)
1058 0 : return gpg_error (GPG_ERR_INV_VALUE);
1059 :
1060 0 : if (!engine->ops->passwd)
1061 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1062 :
1063 0 : return (*engine->ops->passwd) (engine->engine, key, flags);
1064 : }
1065 :
1066 :
1067 : /* Set the pinentry mode for ENGINE to MODE. */
1068 : gpgme_error_t
1069 524 : _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1070 : {
1071 524 : if (!engine)
1072 0 : return gpg_error (GPG_ERR_INV_VALUE);
1073 :
1074 524 : if (!engine->ops->set_pinentry_mode)
1075 14 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1076 :
1077 510 : return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1078 : }
1079 :
1080 :
1081 : gpgme_error_t
1082 0 : _gpgme_engine_op_spawn (engine_t engine,
1083 : const char *file, const char *argv[],
1084 : gpgme_data_t datain,
1085 : gpgme_data_t dataout, gpgme_data_t dataerr,
1086 : unsigned int flags)
1087 : {
1088 0 : if (!engine)
1089 0 : return gpg_error (GPG_ERR_INV_VALUE);
1090 :
1091 0 : if (!engine->ops->opspawn)
1092 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1093 :
1094 0 : return (*engine->ops->opspawn) (engine->engine, file, argv,
1095 : datain, dataout, dataerr, flags);
1096 : }
|