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