w32: Better protect the IO-system's fd_table
[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 <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpgme.h"
30 #include "util.h"
31 #include "sema.h"
32 #include "ops.h"
33 #include "debug.h"
34
35 #include "engine.h"
36 #include "engine-backend.h"
37
38
39 struct engine
40 {
41   struct engine_ops *ops;
42   void *engine;
43 };
44
45
46 static struct engine_ops *engine_ops[] =
47   {
48     &_gpgme_engine_ops_gpg,             /* OpenPGP.  */
49     &_gpgme_engine_ops_gpgsm,           /* CMS.  */
50     &_gpgme_engine_ops_gpgconf,         /* gpg-conf.  */
51     &_gpgme_engine_ops_assuan,          /* Low-Level Assuan.  */
52     &_gpgme_engine_ops_g13,             /* Crypto VFS.  */
53 #ifdef ENABLE_UISERVER
54     &_gpgme_engine_ops_uiserver,        /* UI-Server.  */
55 #else
56     NULL,
57 #endif
58     &_gpgme_engine_ops_spawn
59   };
60
61
62 /* The engine info.  */
63 static gpgme_engine_info_t engine_info;
64 DEFINE_STATIC_LOCK (engine_info_lock);
65
66 /* If non-NULL, the minimal version required for all engines.  */
67 static char *engine_minimal_version;
68
69
70 \f
71 /* Get the file name of the engine for PROTOCOL.  */
72 static const char *
73 engine_get_file_name (gpgme_protocol_t proto)
74 {
75   if (proto > DIM (engine_ops))
76     return NULL;
77
78   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
79     return (*engine_ops[proto]->get_file_name) ();
80   else
81     return NULL;
82 }
83
84
85 /* Get the standard home dir of the engine for PROTOCOL.  */
86 static const char *
87 engine_get_home_dir (gpgme_protocol_t proto)
88 {
89   if (proto > DIM (engine_ops))
90     return NULL;
91
92   if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
93     return (*engine_ops[proto]->get_home_dir) ();
94   else
95     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 engine_get_version (gpgme_protocol_t proto, const char *file_name)
104 {
105   if (proto > DIM (engine_ops))
106     return NULL;
107
108   if (engine_ops[proto] && engine_ops[proto]->get_version)
109     return (*engine_ops[proto]->get_version) (file_name);
110   else
111     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 engine_get_req_version (gpgme_protocol_t proto)
119 {
120   if (proto > DIM (engine_ops))
121     return NULL;
122
123   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
124     return (*engine_ops[proto]->get_req_version) ();
125   else
126     return NULL;
127 }
128
129
130 /* Verify the version requirement for the engine for PROTOCOL.  */
131 gpgme_error_t
132 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   LOCK (engine_info_lock);
139   info = engine_info;
140   if (!info)
141     {
142       /* Make sure it is initialized.  */
143       UNLOCK (engine_info_lock);
144       err = gpgme_get_engine_info (&info);
145       if (err)
146         return err;
147
148       LOCK (engine_info_lock);
149     }
150
151   while (info && info->protocol != proto)
152     info = info->next;
153
154   if (!info)
155     result = 0;
156   else
157     result = _gpgme_compare_versions (info->version,
158                                       info->req_version);
159
160   UNLOCK (engine_info_lock);
161   return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
162 }
163
164
165 /* Release the engine info INFO.  */
166 void
167 _gpgme_engine_info_release (gpgme_engine_info_t info)
168 {
169   while (info)
170     {
171       gpgme_engine_info_t next_info = info->next;
172
173       if (info->file_name)
174         free (info->file_name);
175       if (info->home_dir)
176         free (info->home_dir);
177       if (info->version)
178         free (info->version);
179       free (info);
180       info = next_info;
181     }
182 }
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 _gpgme_set_engine_minimal_version (const char *value)
190 {
191   free (engine_minimal_version);
192   if (value)
193     {
194       engine_minimal_version = strdup (value);
195       return !engine_minimal_version;
196     }
197   else
198     {
199       engine_minimal_version = NULL;
200       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 gpgme_get_engine_info (gpgme_engine_info_t *info)
211 {
212   gpgme_error_t err;
213
214   LOCK (engine_info_lock);
215   if (!engine_info)
216     {
217       gpgme_engine_info_t *lastp = &engine_info;
218       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       err = 0;
228       for (proto = 0; proto < DIM (proto_list); proto++)
229         {
230           const char *ofile_name = engine_get_file_name (proto_list[proto]);
231           const char *ohome_dir  = engine_get_home_dir (proto_list[proto]);
232           char *version = engine_get_version (proto_list[proto], NULL);
233           char *file_name;
234           char *home_dir;
235
236           if (!ofile_name)
237             continue;
238
239           file_name = strdup (ofile_name);
240           if (!file_name)
241             err = gpg_error_from_syserror ();
242
243           if (ohome_dir)
244             {
245               home_dir = strdup (ohome_dir);
246               if (!home_dir && !err)
247                 err = gpg_error_from_syserror ();
248             }
249           else
250             home_dir = NULL;
251
252           *lastp = calloc (1, sizeof (*engine_info));
253           if (!*lastp && !err)
254             err = gpg_error_from_syserror ();
255
256           /* Check against the optional minimal engine version.  */
257           if (!err && version && engine_minimal_version
258               && !_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               err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
264 #endif
265             }
266
267           /* Now set the dummy version for pseudo engines.  */
268           if (!err && !version)
269             {
270               version = strdup ("1.0.0");
271               if (!version)
272                 err = gpg_error_from_syserror ();
273             }
274
275           if (err)
276             {
277               _gpgme_engine_info_release (engine_info);
278               engine_info = NULL;
279
280               if (file_name)
281                 free (file_name);
282               if (home_dir)
283                 free (home_dir);
284               if (version)
285                 free (version);
286
287               UNLOCK (engine_info_lock);
288               return err;
289             }
290
291           (*lastp)->protocol = proto_list[proto];
292           (*lastp)->file_name = file_name;
293           (*lastp)->home_dir = home_dir;
294           (*lastp)->version = version;
295           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
296           if (!(*lastp)->req_version)
297             (*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
298           (*lastp)->next = NULL;
299           lastp = &(*lastp)->next;
300         }
301     }
302
303   *info = engine_info;
304   UNLOCK (engine_info_lock);
305   return 0;
306 }
307
308
309 /* Get a deep copy of the engine info and return it in INFO.  */
310 gpgme_error_t
311 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
312 {
313   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   LOCK (engine_info_lock);
319   info = engine_info;
320   if (!info)
321     {
322       /* Make sure it is initialized.  */
323       UNLOCK (engine_info_lock);
324       err = gpgme_get_engine_info (&info);
325       if (err)
326         return err;
327
328       LOCK (engine_info_lock);
329     }
330
331   new_info = NULL;
332   lastp = &new_info;
333
334   while (info)
335     {
336       char *file_name;
337       char *home_dir;
338       char *version;
339
340       assert (info->file_name);
341       file_name = strdup (info->file_name);
342       if (!file_name)
343         err = gpg_error_from_syserror ();
344
345       if (info->home_dir)
346         {
347           home_dir = strdup (info->home_dir);
348           if (!home_dir && !err)
349             err = gpg_error_from_syserror ();
350         }
351       else
352         home_dir = NULL;
353
354       if (info->version)
355         {
356           version = strdup (info->version);
357           if (!version && !err)
358             err = gpg_error_from_syserror ();
359         }
360       else
361         version = NULL;
362
363       *lastp = malloc (sizeof (*engine_info));
364       if (!*lastp && !err)
365         err = gpg_error_from_syserror ();
366
367       if (err)
368         {
369           _gpgme_engine_info_release (new_info);
370           if (file_name)
371             free (file_name);
372           if (home_dir)
373             free (home_dir);
374           if (version)
375             free (version);
376
377           UNLOCK (engine_info_lock);
378           return err;
379         }
380
381       (*lastp)->protocol = info->protocol;
382       (*lastp)->file_name = file_name;
383       (*lastp)->home_dir = home_dir;
384       (*lastp)->version = version;
385       (*lastp)->req_version = info->req_version;
386       (*lastp)->next = NULL;
387       lastp = &(*lastp)->next;
388
389       info = info->next;
390     }
391
392   *r_info = new_info;
393   UNLOCK (engine_info_lock);
394   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 _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   if (proto > DIM (engine_ops))
410     return gpg_error (GPG_ERR_INV_VALUE);
411
412   while (info && info->protocol != proto)
413     info = info->next;
414
415   if (!info)
416     return trace_gpg_error (GPG_ERR_INV_ENGINE);
417
418   /* Prepare new members.  */
419   if (file_name)
420     new_file_name = strdup (file_name);
421   else
422     {
423       const char *ofile_name = engine_get_file_name (proto);
424       assert (ofile_name);
425       new_file_name = strdup (ofile_name);
426     }
427   if (!new_file_name)
428     return gpg_error_from_syserror ();
429
430   if (home_dir)
431     {
432       new_home_dir = strdup (home_dir);
433       if (!new_home_dir)
434         {
435           free (new_file_name);
436           return gpg_error_from_syserror ();
437         }
438     }
439   else
440     {
441       const char *ohome_dir = engine_get_home_dir (proto);
442       if (ohome_dir)
443         {
444           new_home_dir = strdup (ohome_dir);
445           if (!new_home_dir)
446             {
447               free (new_file_name);
448               return gpg_error_from_syserror ();
449             }
450         }
451       else
452         new_home_dir = NULL;
453     }
454
455   new_version = engine_get_version (proto, new_file_name);
456   if (!new_version)
457     {
458       new_version = strdup ("1.0.0"); /* Fake one for dummy entries.  */
459       if (!new_version)
460         {
461           free (new_file_name);
462           free (new_home_dir);
463         }
464     }
465
466   /* Remove the old members.  */
467   assert (info->file_name);
468   free (info->file_name);
469   if (info->home_dir)
470     free (info->home_dir);
471   if (info->version)
472     free (info->version);
473
474   /* Install the new members.  */
475   info->file_name = new_file_name;
476   info->home_dir = new_home_dir;
477   info->version = new_version;
478
479   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 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   LOCK (engine_info_lock);
493   info = engine_info;
494   if (!info)
495     {
496       /* Make sure it is initialized.  */
497       UNLOCK (engine_info_lock);
498       err = gpgme_get_engine_info (&info);
499       if (err)
500         return err;
501
502       LOCK (engine_info_lock);
503     }
504
505   err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
506   UNLOCK (engine_info_lock);
507   return err;
508 }
509
510 \f
511 gpgme_error_t
512 _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
513 {
514   engine_t engine;
515
516   if (!info->file_name || !info->version)
517     return trace_gpg_error (GPG_ERR_INV_ENGINE);
518
519   engine = calloc (1, sizeof *engine);
520   if (!engine)
521     return gpg_error_from_syserror ();
522
523   engine->ops = engine_ops[info->protocol];
524   if (engine->ops->new)
525     {
526       gpgme_error_t err;
527       err = (*engine->ops->new) (&engine->engine,
528                                  info->file_name, info->home_dir,
529                                  info->version);
530       if (err)
531         {
532           free (engine);
533           return err;
534         }
535     }
536   else
537     engine->engine = NULL;
538
539   *r_engine = engine;
540   return 0;
541 }
542
543
544 gpgme_error_t
545 _gpgme_engine_reset (engine_t engine)
546 {
547   if (!engine)
548     return gpg_error (GPG_ERR_INV_VALUE);
549
550   if (!engine->ops->reset)
551     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
552
553   return (*engine->ops->reset) (engine->engine);
554 }
555
556
557 void
558 _gpgme_engine_release (engine_t engine)
559 {
560   if (!engine)
561     return;
562
563   if (engine->ops->release)
564     (*engine->ops->release) (engine->engine);
565   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 _gpgme_engine_set_status_cb (engine_t engine,
574                              gpgme_status_cb_t cb, void *cb_value)
575 {
576   if (!engine)
577     return;
578
579   if (engine->ops->set_status_cb)
580     (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
581 }
582
583
584 void
585 _gpgme_engine_set_status_handler (engine_t engine,
586                                   engine_status_handler_t fnc, void *fnc_value)
587 {
588   if (!engine)
589     return;
590
591   if (engine->ops->set_status_handler)
592     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
593 }
594
595
596 gpgme_error_t
597 _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   if (!engine)
603     return gpg_error (GPG_ERR_INV_VALUE);
604
605   if (!engine->ops->set_command_handler)
606     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
607
608   return (*engine->ops->set_command_handler) (engine->engine,
609                                               fnc, fnc_value, linked_data);
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 gpgme_error_t
655 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
656                           gpgme_data_t plain)
657 {
658   if (!engine)
659     return gpg_error (GPG_ERR_INV_VALUE);
660
661   if (!engine->ops->decrypt)
662     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
663
664   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
665 }
666
667
668 gpgme_error_t
669 _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
670                                  gpgme_data_t plain)
671 {
672   if (!engine)
673     return gpg_error (GPG_ERR_INV_VALUE);
674
675   if (!engine->ops->decrypt_verify)
676     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
677
678   return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain);
679 }
680
681
682 gpgme_error_t
683 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
684                          int allow_secret)
685 {
686   if (!engine)
687     return gpg_error (GPG_ERR_INV_VALUE);
688
689   if (!engine->ops->delete)
690     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
691
692   return (*engine->ops->delete) (engine->engine, key, allow_secret);
693 }
694
695
696 gpgme_error_t
697 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
698                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
699 {
700   if (!engine)
701     return gpg_error (GPG_ERR_INV_VALUE);
702
703   if (!engine->ops->edit)
704     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
705
706   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
707 }
708
709
710 gpgme_error_t
711 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
712                           gpgme_encrypt_flags_t flags,
713                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
714 {
715   if (!engine)
716     return gpg_error (GPG_ERR_INV_VALUE);
717
718   if (!engine->ops->encrypt)
719     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
720
721   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
722                                   use_armor);
723 }
724
725
726 gpgme_error_t
727 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
728                                gpgme_encrypt_flags_t flags,
729                                gpgme_data_t plain, gpgme_data_t ciph,
730                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
731 {
732   if (!engine)
733     return gpg_error (GPG_ERR_INV_VALUE);
734
735   if (!engine->ops->encrypt_sign)
736     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
737
738   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
739                                        plain, ciph, use_armor, ctx);
740 }
741
742
743 gpgme_error_t
744 _gpgme_engine_op_export (engine_t engine, const char *pattern,
745                          gpgme_export_mode_t mode, gpgme_data_t keydata,
746                          int use_armor)
747 {
748   if (!engine)
749     return gpg_error (GPG_ERR_INV_VALUE);
750
751   if (!engine->ops->export)
752     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
753
754   return (*engine->ops->export) (engine->engine, pattern, mode,
755                                  keydata, use_armor);
756 }
757
758
759 gpgme_error_t
760 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
761                              unsigned int reserved, gpgme_data_t keydata,
762                              int use_armor)
763 {
764   if (!engine)
765     return gpg_error (GPG_ERR_INV_VALUE);
766
767   if (!engine->ops->export_ext)
768     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
769
770   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
771                                      keydata, use_armor);
772 }
773
774
775 gpgme_error_t
776 _gpgme_engine_op_genkey (engine_t engine,
777                          const char *userid, const char *algo,
778                          unsigned long reserved, unsigned long expires,
779                          gpgme_key_t key, unsigned int flags,
780                          gpgme_data_t help_data,
781                          unsigned int extraflags,
782                          gpgme_data_t pubkey, gpgme_data_t seckey)
783 {
784   if (!engine)
785     return gpg_error (GPG_ERR_INV_VALUE);
786
787   if (!engine->ops->genkey)
788     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
789
790   return (*engine->ops->genkey) (engine->engine,
791                                  userid, algo, reserved, expires, key, flags,
792                                  help_data, extraflags,
793                                  pubkey, seckey);
794 }
795
796
797 gpgme_error_t
798 _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
799                           unsigned long expires, unsigned int flags,
800                           gpgme_ctx_t ctx)
801 {
802   if (!engine)
803     return gpg_error (GPG_ERR_INV_VALUE);
804
805   if (!engine->ops->keysign)
806     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
807
808   return (*engine->ops->keysign) (engine->engine,
809                                   key, userid, expires, flags, ctx);
810 }
811
812
813 gpgme_error_t
814 _gpgme_engine_op_tofu_policy (engine_t engine,
815                               gpgme_key_t key,  gpgme_tofu_policy_t policy)
816 {
817   if (!engine)
818     return gpg_error (GPG_ERR_INV_VALUE);
819
820   if (!engine->ops->tofu_policy)
821     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
822
823   return (*engine->ops->tofu_policy) (engine->engine, key, policy);
824 }
825
826
827 gpgme_error_t
828 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
829                          gpgme_key_t *keyarray)
830 {
831   if (!engine)
832     return gpg_error (GPG_ERR_INV_VALUE);
833
834   if (!engine->ops->import)
835     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
836
837   return (*engine->ops->import) (engine->engine, keydata, keyarray);
838 }
839
840
841 gpgme_error_t
842 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
843                           int secret_only, gpgme_keylist_mode_t mode,
844                           int engine_flags)
845 {
846   if (!engine)
847     return gpg_error (GPG_ERR_INV_VALUE);
848
849   if (!engine->ops->keylist)
850     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
851
852   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
853                                   engine_flags);
854 }
855
856
857 gpgme_error_t
858 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
859                               int secret_only, int reserved,
860                               gpgme_keylist_mode_t mode, int engine_flags)
861 {
862   if (!engine)
863     return gpg_error (GPG_ERR_INV_VALUE);
864
865   if (!engine->ops->keylist_ext)
866     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
867
868   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
869                                       reserved, mode, engine_flags);
870 }
871
872
873 gpgme_error_t
874 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
875                        gpgme_sig_mode_t mode, int use_armor,
876                        int use_textmode, int include_certs,
877                        gpgme_ctx_t ctx /* FIXME */)
878 {
879   if (!engine)
880     return gpg_error (GPG_ERR_INV_VALUE);
881
882   if (!engine->ops->sign)
883     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
884
885   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
886                                use_textmode, include_certs, ctx);
887 }
888
889
890 gpgme_error_t
891 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
892 {
893   if (!engine)
894     return gpg_error (GPG_ERR_INV_VALUE);
895
896   if (!engine->ops->trustlist)
897     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
898
899   return (*engine->ops->trustlist) (engine->engine, pattern);
900 }
901
902
903 gpgme_error_t
904 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
905                          gpgme_data_t signed_text, gpgme_data_t plaintext,
906                          gpgme_ctx_t ctx)
907 {
908   if (!engine)
909     return gpg_error (GPG_ERR_INV_VALUE);
910
911   if (!engine->ops->verify)
912     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
913
914   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
915                                  ctx);
916 }
917
918
919 gpgme_error_t
920 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
921                               unsigned int flags)
922 {
923   if (!engine)
924     return gpg_error (GPG_ERR_INV_VALUE);
925
926   if (!engine->ops->getauditlog)
927     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
928
929   return (*engine->ops->getauditlog) (engine->engine, output, flags);
930 }
931
932
933 gpgme_error_t
934 _gpgme_engine_op_assuan_transact (engine_t engine,
935                                   const char *command,
936                                   gpgme_assuan_data_cb_t data_cb,
937                                   void *data_cb_value,
938                                   gpgme_assuan_inquire_cb_t inq_cb,
939                                   void *inq_cb_value,
940                                   gpgme_assuan_status_cb_t status_cb,
941                                   void *status_cb_value)
942 {
943   if (!engine)
944     return gpg_error (GPG_ERR_INV_VALUE);
945
946   if (!engine->ops->opassuan_transact)
947     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
948
949   return (*engine->ops->opassuan_transact) (engine->engine,
950                                             command,
951                                             data_cb, data_cb_value,
952                                             inq_cb, inq_cb_value,
953                                             status_cb, status_cb_value);
954 }
955
956
957 gpgme_error_t
958 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
959 {
960   if (!engine)
961     return gpg_error (GPG_ERR_INV_VALUE);
962
963   if (!engine->ops->conf_load)
964     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
965
966   return (*engine->ops->conf_load) (engine->engine, conf_p);
967 }
968
969
970 gpgme_error_t
971 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
972 {
973   if (!engine)
974     return gpg_error (GPG_ERR_INV_VALUE);
975
976   if (!engine->ops->conf_save)
977     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
978
979   return (*engine->ops->conf_save) (engine->engine, conf);
980 }
981
982
983 gpgme_error_t
984 _gpgme_engine_op_query_swdb (engine_t engine,
985                              const char *name, const char *iversion,
986                              gpgme_query_swdb_result_t result)
987 {
988   if (!engine)
989     return gpg_error (GPG_ERR_INV_VALUE);
990
991   if (!engine->ops->query_swdb)
992     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
993
994   return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
995 }
996
997
998 void
999 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
1000 {
1001   if (!engine)
1002     return;
1003
1004   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
1005 }
1006
1007
1008 void
1009 _gpgme_engine_io_event (engine_t engine,
1010                         gpgme_event_io_t type, void *type_data)
1011 {
1012   if (!engine)
1013     return;
1014
1015   (*engine->ops->io_event) (engine->engine, type, type_data);
1016 }
1017
1018
1019 /* Cancel the session and the pending operation if any.  */
1020 gpgme_error_t
1021 _gpgme_engine_cancel (engine_t engine)
1022 {
1023   if (!engine)
1024     return gpg_error (GPG_ERR_INV_VALUE);
1025
1026   if (!engine->ops->cancel)
1027     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1028
1029   return (*engine->ops->cancel) (engine->engine);
1030 }
1031
1032
1033 /* Cancel the pending operation, but not the complete session.  */
1034 gpgme_error_t
1035 _gpgme_engine_cancel_op (engine_t engine)
1036 {
1037   if (!engine)
1038     return gpg_error (GPG_ERR_INV_VALUE);
1039
1040   if (!engine->ops->cancel_op)
1041     return 0;
1042
1043   return (*engine->ops->cancel_op) (engine->engine);
1044 }
1045
1046
1047 /* Change the passphrase for KEY.  */
1048 gpgme_error_t
1049 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
1050                          unsigned int flags)
1051 {
1052   if (!engine)
1053     return gpg_error (GPG_ERR_INV_VALUE);
1054
1055   if (!engine->ops->passwd)
1056     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1057
1058   return (*engine->ops->passwd) (engine->engine, key, flags);
1059 }
1060
1061
1062 /* Set the pinentry mode for ENGINE to MODE.  */
1063 gpgme_error_t
1064 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1065 {
1066   if (!engine)
1067     return gpg_error (GPG_ERR_INV_VALUE);
1068
1069   if (!engine->ops->set_pinentry_mode)
1070     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1071
1072   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1073 }
1074
1075
1076 gpgme_error_t
1077 _gpgme_engine_op_spawn (engine_t engine,
1078                         const char *file, const char *argv[],
1079                         gpgme_data_t datain,
1080                         gpgme_data_t dataout, gpgme_data_t dataerr,
1081                         unsigned int flags)
1082 {
1083   if (!engine)
1084     return gpg_error (GPG_ERR_INV_VALUE);
1085
1086   if (!engine->ops->opspawn)
1087     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1088
1089   return (*engine->ops->opspawn) (engine->engine, file, argv,
1090                                   datain, dataout, dataerr, flags);
1091 }