Fix gpg_addkey() to work with GPGME_CREATE_NOPASSWD as well.
[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://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, int export_session_key,
657                           const char *override_session_key)
658 {
659   if (!engine)
660     return gpg_error (GPG_ERR_INV_VALUE);
661
662   if (!engine->ops->decrypt)
663     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
664
665   return (*engine->ops->decrypt) (engine->engine, ciph, plain,
666                                   export_session_key, override_session_key);
667 }
668
669
670 gpgme_error_t
671 _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
672                                  gpgme_data_t plain, int export_session_key,
673                                  const char *override_session_key)
674 {
675   if (!engine)
676     return gpg_error (GPG_ERR_INV_VALUE);
677
678   if (!engine->ops->decrypt_verify)
679     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
680
681   return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain,
682                                          export_session_key,
683                                          override_session_key);
684 }
685
686
687 gpgme_error_t
688 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
689                          int allow_secret)
690 {
691   if (!engine)
692     return gpg_error (GPG_ERR_INV_VALUE);
693
694   if (!engine->ops->delete)
695     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
696
697   return (*engine->ops->delete) (engine->engine, key, allow_secret);
698 }
699
700
701 gpgme_error_t
702 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
703                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
704 {
705   if (!engine)
706     return gpg_error (GPG_ERR_INV_VALUE);
707
708   if (!engine->ops->edit)
709     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
710
711   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
712 }
713
714
715 gpgme_error_t
716 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
717                           gpgme_encrypt_flags_t flags,
718                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
719 {
720   if (!engine)
721     return gpg_error (GPG_ERR_INV_VALUE);
722
723   if (!engine->ops->encrypt)
724     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
725
726   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
727                                   use_armor);
728 }
729
730
731 gpgme_error_t
732 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
733                                gpgme_encrypt_flags_t flags,
734                                gpgme_data_t plain, gpgme_data_t ciph,
735                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
736 {
737   if (!engine)
738     return gpg_error (GPG_ERR_INV_VALUE);
739
740   if (!engine->ops->encrypt_sign)
741     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
742
743   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
744                                        plain, ciph, use_armor, ctx);
745 }
746
747
748 gpgme_error_t
749 _gpgme_engine_op_export (engine_t engine, const char *pattern,
750                          gpgme_export_mode_t mode, gpgme_data_t keydata,
751                          int use_armor)
752 {
753   if (!engine)
754     return gpg_error (GPG_ERR_INV_VALUE);
755
756   if (!engine->ops->export)
757     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
758
759   return (*engine->ops->export) (engine->engine, pattern, mode,
760                                  keydata, use_armor);
761 }
762
763
764 gpgme_error_t
765 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
766                              unsigned int reserved, gpgme_data_t keydata,
767                              int use_armor)
768 {
769   if (!engine)
770     return gpg_error (GPG_ERR_INV_VALUE);
771
772   if (!engine->ops->export_ext)
773     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
774
775   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
776                                      keydata, use_armor);
777 }
778
779
780 gpgme_error_t
781 _gpgme_engine_op_genkey (engine_t engine,
782                          const char *userid, const char *algo,
783                          unsigned long reserved, unsigned long expires,
784                          gpgme_key_t key, unsigned int flags,
785                          gpgme_data_t help_data,
786                          unsigned int extraflags,
787                          gpgme_data_t pubkey, gpgme_data_t seckey)
788 {
789   if (!engine)
790     return gpg_error (GPG_ERR_INV_VALUE);
791
792   if (!engine->ops->genkey)
793     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
794
795   return (*engine->ops->genkey) (engine->engine,
796                                  userid, algo, reserved, expires, key, flags,
797                                  help_data, extraflags,
798                                  pubkey, seckey);
799 }
800
801
802 gpgme_error_t
803 _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
804                           unsigned long expires, unsigned int flags,
805                           gpgme_ctx_t ctx)
806 {
807   if (!engine)
808     return gpg_error (GPG_ERR_INV_VALUE);
809
810   if (!engine->ops->keysign)
811     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
812
813   return (*engine->ops->keysign) (engine->engine,
814                                   key, userid, expires, flags, ctx);
815 }
816
817
818 gpgme_error_t
819 _gpgme_engine_op_tofu_policy (engine_t engine,
820                               gpgme_key_t key,  gpgme_tofu_policy_t policy)
821 {
822   if (!engine)
823     return gpg_error (GPG_ERR_INV_VALUE);
824
825   if (!engine->ops->tofu_policy)
826     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
827
828   return (*engine->ops->tofu_policy) (engine->engine, key, policy);
829 }
830
831
832 gpgme_error_t
833 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
834                          gpgme_key_t *keyarray)
835 {
836   if (!engine)
837     return gpg_error (GPG_ERR_INV_VALUE);
838
839   if (!engine->ops->import)
840     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
841
842   return (*engine->ops->import) (engine->engine, keydata, keyarray);
843 }
844
845
846 gpgme_error_t
847 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
848                           int secret_only, gpgme_keylist_mode_t mode,
849                           int engine_flags)
850 {
851   if (!engine)
852     return gpg_error (GPG_ERR_INV_VALUE);
853
854   if (!engine->ops->keylist)
855     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
856
857   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
858                                   engine_flags);
859 }
860
861
862 gpgme_error_t
863 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
864                               int secret_only, int reserved,
865                               gpgme_keylist_mode_t mode, int engine_flags)
866 {
867   if (!engine)
868     return gpg_error (GPG_ERR_INV_VALUE);
869
870   if (!engine->ops->keylist_ext)
871     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
872
873   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
874                                       reserved, mode, engine_flags);
875 }
876
877
878 gpgme_error_t
879 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
880                        gpgme_sig_mode_t mode, int use_armor,
881                        int use_textmode, int include_certs,
882                        gpgme_ctx_t ctx /* FIXME */)
883 {
884   if (!engine)
885     return gpg_error (GPG_ERR_INV_VALUE);
886
887   if (!engine->ops->sign)
888     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
889
890   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
891                                use_textmode, include_certs, ctx);
892 }
893
894
895 gpgme_error_t
896 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
897 {
898   if (!engine)
899     return gpg_error (GPG_ERR_INV_VALUE);
900
901   if (!engine->ops->trustlist)
902     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
903
904   return (*engine->ops->trustlist) (engine->engine, pattern);
905 }
906
907
908 gpgme_error_t
909 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
910                          gpgme_data_t signed_text, gpgme_data_t plaintext,
911                          gpgme_ctx_t ctx)
912 {
913   if (!engine)
914     return gpg_error (GPG_ERR_INV_VALUE);
915
916   if (!engine->ops->verify)
917     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
918
919   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
920                                  ctx);
921 }
922
923
924 gpgme_error_t
925 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
926                               unsigned int flags)
927 {
928   if (!engine)
929     return gpg_error (GPG_ERR_INV_VALUE);
930
931   if (!engine->ops->getauditlog)
932     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
933
934   return (*engine->ops->getauditlog) (engine->engine, output, flags);
935 }
936
937
938 gpgme_error_t
939 _gpgme_engine_op_assuan_transact (engine_t engine,
940                                   const char *command,
941                                   gpgme_assuan_data_cb_t data_cb,
942                                   void *data_cb_value,
943                                   gpgme_assuan_inquire_cb_t inq_cb,
944                                   void *inq_cb_value,
945                                   gpgme_assuan_status_cb_t status_cb,
946                                   void *status_cb_value)
947 {
948   if (!engine)
949     return gpg_error (GPG_ERR_INV_VALUE);
950
951   if (!engine->ops->opassuan_transact)
952     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
953
954   return (*engine->ops->opassuan_transact) (engine->engine,
955                                             command,
956                                             data_cb, data_cb_value,
957                                             inq_cb, inq_cb_value,
958                                             status_cb, status_cb_value);
959 }
960
961
962 gpgme_error_t
963 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
964 {
965   if (!engine)
966     return gpg_error (GPG_ERR_INV_VALUE);
967
968   if (!engine->ops->conf_load)
969     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
970
971   return (*engine->ops->conf_load) (engine->engine, conf_p);
972 }
973
974
975 gpgme_error_t
976 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
977 {
978   if (!engine)
979     return gpg_error (GPG_ERR_INV_VALUE);
980
981   if (!engine->ops->conf_save)
982     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
983
984   return (*engine->ops->conf_save) (engine->engine, conf);
985 }
986
987
988 gpgme_error_t
989 _gpgme_engine_op_query_swdb (engine_t engine,
990                              const char *name, const char *iversion,
991                              gpgme_query_swdb_result_t result)
992 {
993   if (!engine)
994     return gpg_error (GPG_ERR_INV_VALUE);
995
996   if (!engine->ops->query_swdb)
997     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
998
999   return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
1000 }
1001
1002
1003 void
1004 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
1005 {
1006   if (!engine)
1007     return;
1008
1009   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
1010 }
1011
1012
1013 void
1014 _gpgme_engine_io_event (engine_t engine,
1015                         gpgme_event_io_t type, void *type_data)
1016 {
1017   if (!engine)
1018     return;
1019
1020   (*engine->ops->io_event) (engine->engine, type, type_data);
1021 }
1022
1023
1024 /* Cancel the session and the pending operation if any.  */
1025 gpgme_error_t
1026 _gpgme_engine_cancel (engine_t engine)
1027 {
1028   if (!engine)
1029     return gpg_error (GPG_ERR_INV_VALUE);
1030
1031   if (!engine->ops->cancel)
1032     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1033
1034   return (*engine->ops->cancel) (engine->engine);
1035 }
1036
1037
1038 /* Cancel the pending operation, but not the complete session.  */
1039 gpgme_error_t
1040 _gpgme_engine_cancel_op (engine_t engine)
1041 {
1042   if (!engine)
1043     return gpg_error (GPG_ERR_INV_VALUE);
1044
1045   if (!engine->ops->cancel_op)
1046     return 0;
1047
1048   return (*engine->ops->cancel_op) (engine->engine);
1049 }
1050
1051
1052 /* Change the passphrase for KEY.  */
1053 gpgme_error_t
1054 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
1055                          unsigned int flags)
1056 {
1057   if (!engine)
1058     return gpg_error (GPG_ERR_INV_VALUE);
1059
1060   if (!engine->ops->passwd)
1061     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1062
1063   return (*engine->ops->passwd) (engine->engine, key, flags);
1064 }
1065
1066
1067 /* Set the pinentry mode for ENGINE to MODE.  */
1068 gpgme_error_t
1069 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1070 {
1071   if (!engine)
1072     return gpg_error (GPG_ERR_INV_VALUE);
1073
1074   if (!engine->ops->set_pinentry_mode)
1075     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1076
1077   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1078 }
1079
1080
1081 gpgme_error_t
1082 _gpgme_engine_op_spawn (engine_t engine,
1083                         const char *file, const char *argv[],
1084                         gpgme_data_t datain,
1085                         gpgme_data_t dataout, gpgme_data_t dataerr,
1086                         unsigned int flags)
1087 {
1088   if (!engine)
1089     return gpg_error (GPG_ERR_INV_VALUE);
1090
1091   if (!engine->ops->opspawn)
1092     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1093
1094   return (*engine->ops->opspawn) (engine->engine, file, argv,
1095                                   datain, dataout, dataerr, flags);
1096 }