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