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