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
5 This file is part of GPGME.
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.
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.
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/>.
36 #include "engine-backend.h"
41 struct engine_ops *ops;
46 static struct engine_ops *engine_ops[] =
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. */
58 &_gpgme_engine_ops_spawn
62 /* The engine info. */
63 static gpgme_engine_info_t engine_info;
64 DEFINE_STATIC_LOCK (engine_info_lock);
67 /* Get the file name of the engine for PROTOCOL. */
69 engine_get_file_name (gpgme_protocol_t proto)
71 if (proto > DIM (engine_ops))
74 if (engine_ops[proto] && engine_ops[proto]->get_file_name)
75 return (*engine_ops[proto]->get_file_name) ();
81 /* Get the standard home dir of the engine for PROTOCOL. */
83 engine_get_home_dir (gpgme_protocol_t proto)
85 if (proto > DIM (engine_ops))
88 if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
89 return (*engine_ops[proto]->get_home_dir) ();
95 /* Get a malloced string containing the version number of the engine
98 engine_get_version (gpgme_protocol_t proto, const char *file_name)
100 if (proto > DIM (engine_ops))
103 if (engine_ops[proto] && engine_ops[proto]->get_version)
104 return (*engine_ops[proto]->get_version) (file_name);
110 /* Get the required version number of the engine for PROTOCOL. */
112 engine_get_req_version (gpgme_protocol_t proto)
114 if (proto > DIM (engine_ops))
117 if (engine_ops[proto] && engine_ops[proto]->get_req_version)
118 return (*engine_ops[proto]->get_req_version) ();
124 /* Verify the version requirement for the engine for PROTOCOL. */
126 gpgme_engine_check_version (gpgme_protocol_t proto)
129 gpgme_engine_info_t info;
132 LOCK (engine_info_lock);
136 /* Make sure it is initialized. */
137 UNLOCK (engine_info_lock);
138 err = gpgme_get_engine_info (&info);
142 LOCK (engine_info_lock);
145 while (info && info->protocol != proto)
151 result = _gpgme_compare_versions (info->version,
154 UNLOCK (engine_info_lock);
155 return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
159 /* Release the engine info INFO. */
161 _gpgme_engine_info_release (gpgme_engine_info_t info)
165 gpgme_engine_info_t next_info = info->next;
167 assert (info->file_name);
168 free (info->file_name);
170 free (info->home_dir);
172 free (info->version);
179 /* Get the information about the configured and installed engines. A
180 pointer to the first engine in the statically allocated linked list
181 is returned in *INFO. If an error occurs, it is returned. The
182 returned data is valid until the next gpgme_set_engine_info. */
184 gpgme_get_engine_info (gpgme_engine_info_t *info)
188 LOCK (engine_info_lock);
191 gpgme_engine_info_t *lastp = &engine_info;
192 gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
194 GPGME_PROTOCOL_GPGCONF,
195 GPGME_PROTOCOL_ASSUAN,
197 GPGME_PROTOCOL_UISERVER,
198 GPGME_PROTOCOL_SPAWN };
202 for (proto = 0; proto < DIM (proto_list); proto++)
204 const char *ofile_name = engine_get_file_name (proto_list[proto]);
205 const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
212 file_name = strdup (ofile_name);
214 err = gpg_error_from_syserror ();
218 home_dir = strdup (ohome_dir);
219 if (!home_dir && !err)
220 err = gpg_error_from_syserror ();
225 *lastp = malloc (sizeof (*engine_info));
227 err = gpg_error_from_syserror ();
231 _gpgme_engine_info_release (engine_info);
239 UNLOCK (engine_info_lock);
243 (*lastp)->protocol = proto_list[proto];
244 (*lastp)->file_name = file_name;
245 (*lastp)->home_dir = home_dir;
246 (*lastp)->version = engine_get_version (proto_list[proto], NULL);
247 (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
248 (*lastp)->next = NULL;
249 lastp = &(*lastp)->next;
254 UNLOCK (engine_info_lock);
259 /* Get a deep copy of the engine info and return it in INFO. */
261 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
263 gpgme_error_t err = 0;
264 gpgme_engine_info_t info;
265 gpgme_engine_info_t new_info;
266 gpgme_engine_info_t *lastp;
268 LOCK (engine_info_lock);
272 /* Make sure it is initialized. */
273 UNLOCK (engine_info_lock);
274 err = gpgme_get_engine_info (&info);
278 LOCK (engine_info_lock);
290 assert (info->file_name);
291 file_name = strdup (info->file_name);
293 err = gpg_error_from_syserror ();
297 home_dir = strdup (info->home_dir);
298 if (!home_dir && !err)
299 err = gpg_error_from_syserror ();
306 version = strdup (info->version);
307 if (!version && !err)
308 err = gpg_error_from_syserror ();
313 *lastp = malloc (sizeof (*engine_info));
315 err = gpg_error_from_syserror ();
319 _gpgme_engine_info_release (new_info);
327 UNLOCK (engine_info_lock);
331 (*lastp)->protocol = info->protocol;
332 (*lastp)->file_name = file_name;
333 (*lastp)->home_dir = home_dir;
334 (*lastp)->version = version;
335 (*lastp)->req_version = info->req_version;
336 (*lastp)->next = NULL;
337 lastp = &(*lastp)->next;
343 UNLOCK (engine_info_lock);
348 /* Set the engine info for the info list INFO, protocol PROTO, to the
349 file name FILE_NAME and the home directory HOME_DIR. */
351 _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
352 const char *file_name, const char *home_dir)
357 /* FIXME: Use some PROTO_MAX definition. */
358 if (proto > DIM (engine_ops))
359 return gpg_error (GPG_ERR_INV_VALUE);
361 while (info && info->protocol != proto)
365 return trace_gpg_error (GPG_ERR_INV_ENGINE);
367 /* Prepare new members. */
369 new_file_name = strdup (file_name);
372 const char *ofile_name = engine_get_file_name (proto);
374 new_file_name = strdup (ofile_name);
377 return gpg_error_from_syserror ();
381 new_home_dir = strdup (home_dir);
384 free (new_file_name);
385 return gpg_error_from_syserror ();
390 const char *ohome_dir = engine_get_home_dir (proto);
393 new_home_dir = strdup (ohome_dir);
396 free (new_file_name);
397 return gpg_error_from_syserror ();
404 /* Remove the old members. */
405 assert (info->file_name);
406 free (info->file_name);
408 free (info->home_dir);
410 free (info->version);
412 /* Install the new members. */
413 info->file_name = new_file_name;
414 info->home_dir = new_home_dir;
415 info->version = engine_get_version (proto, new_file_name);
421 /* Set the default engine info for the protocol PROTO to the file name
422 FILE_NAME and the home directory HOME_DIR. */
424 gpgme_set_engine_info (gpgme_protocol_t proto,
425 const char *file_name, const char *home_dir)
428 gpgme_engine_info_t info;
430 LOCK (engine_info_lock);
434 /* Make sure it is initialized. */
435 UNLOCK (engine_info_lock);
436 err = gpgme_get_engine_info (&info);
440 LOCK (engine_info_lock);
443 err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
444 UNLOCK (engine_info_lock);
450 _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
454 if (!info->file_name || !info->version)
455 return trace_gpg_error (GPG_ERR_INV_ENGINE);
457 engine = calloc (1, sizeof *engine);
459 return gpg_error_from_syserror ();
461 engine->ops = engine_ops[info->protocol];
462 if (engine->ops->new)
465 err = (*engine->ops->new) (&engine->engine,
466 info->file_name, info->home_dir);
474 engine->engine = NULL;
482 _gpgme_engine_reset (engine_t engine)
485 return gpg_error (GPG_ERR_INV_VALUE);
487 if (!engine->ops->reset)
488 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
490 return (*engine->ops->reset) (engine->engine);
495 _gpgme_engine_release (engine_t engine)
500 if (engine->ops->release)
501 (*engine->ops->release) (engine->engine);
506 /* Set a status callback which is used to monitor the status values
507 * before they are passed to a handler set with
508 * _gpgme_engine_set_status_handler. */
510 _gpgme_engine_set_status_cb (engine_t engine,
511 gpgme_status_cb_t cb, void *cb_value)
516 if (engine->ops->set_status_cb)
517 (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
522 _gpgme_engine_set_status_handler (engine_t engine,
523 engine_status_handler_t fnc, void *fnc_value)
528 if (engine->ops->set_status_handler)
529 (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
534 _gpgme_engine_set_command_handler (engine_t engine,
535 engine_command_handler_t fnc,
537 gpgme_data_t linked_data)
540 return gpg_error (GPG_ERR_INV_VALUE);
542 if (!engine->ops->set_command_handler)
543 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
545 return (*engine->ops->set_command_handler) (engine->engine,
546 fnc, fnc_value, linked_data);
550 _gpgme_engine_set_colon_line_handler (engine_t engine,
551 engine_colon_line_handler_t fnc,
555 return gpg_error (GPG_ERR_INV_VALUE);
557 if (!engine->ops->set_colon_line_handler)
558 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
560 return (*engine->ops->set_colon_line_handler) (engine->engine,
565 _gpgme_engine_set_locale (engine_t engine, int category,
569 return gpg_error (GPG_ERR_INV_VALUE);
571 if (!engine->ops->set_locale)
572 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
574 return (*engine->ops->set_locale) (engine->engine, category, value);
579 _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
582 return gpg_error (GPG_ERR_INV_VALUE);
584 if (!engine->ops->set_protocol)
585 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
587 return (*engine->ops->set_protocol) (engine->engine, protocol);
592 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
596 return gpg_error (GPG_ERR_INV_VALUE);
598 if (!engine->ops->decrypt)
599 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
601 return (*engine->ops->decrypt) (engine->engine, ciph, plain);
606 _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
610 return gpg_error (GPG_ERR_INV_VALUE);
612 if (!engine->ops->decrypt_verify)
613 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
615 return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain);
620 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
624 return gpg_error (GPG_ERR_INV_VALUE);
626 if (!engine->ops->delete)
627 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
629 return (*engine->ops->delete) (engine->engine, key, allow_secret);
634 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
635 gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
638 return gpg_error (GPG_ERR_INV_VALUE);
640 if (!engine->ops->edit)
641 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
643 return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
648 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
649 gpgme_encrypt_flags_t flags,
650 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
653 return gpg_error (GPG_ERR_INV_VALUE);
655 if (!engine->ops->encrypt)
656 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
658 return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
664 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
665 gpgme_encrypt_flags_t flags,
666 gpgme_data_t plain, gpgme_data_t ciph,
667 int use_armor, gpgme_ctx_t ctx /* FIXME */)
670 return gpg_error (GPG_ERR_INV_VALUE);
672 if (!engine->ops->encrypt_sign)
673 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
675 return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
676 plain, ciph, use_armor, ctx);
681 _gpgme_engine_op_export (engine_t engine, const char *pattern,
682 gpgme_export_mode_t mode, gpgme_data_t keydata,
686 return gpg_error (GPG_ERR_INV_VALUE);
688 if (!engine->ops->export)
689 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
691 return (*engine->ops->export) (engine->engine, pattern, mode,
697 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
698 unsigned int reserved, gpgme_data_t keydata,
702 return gpg_error (GPG_ERR_INV_VALUE);
704 if (!engine->ops->export_ext)
705 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
707 return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
713 _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
714 int use_armor, gpgme_data_t pubkey,
718 return gpg_error (GPG_ERR_INV_VALUE);
720 if (!engine->ops->genkey)
721 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
723 return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
729 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
730 gpgme_key_t *keyarray)
733 return gpg_error (GPG_ERR_INV_VALUE);
735 if (!engine->ops->import)
736 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
738 return (*engine->ops->import) (engine->engine, keydata, keyarray);
743 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
744 int secret_only, gpgme_keylist_mode_t mode,
748 return gpg_error (GPG_ERR_INV_VALUE);
750 if (!engine->ops->keylist)
751 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
753 return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
759 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
760 int secret_only, int reserved,
761 gpgme_keylist_mode_t mode, int engine_flags)
764 return gpg_error (GPG_ERR_INV_VALUE);
766 if (!engine->ops->keylist_ext)
767 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
769 return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
770 reserved, mode, engine_flags);
775 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
776 gpgme_sig_mode_t mode, int use_armor,
777 int use_textmode, int include_certs,
778 gpgme_ctx_t ctx /* FIXME */)
781 return gpg_error (GPG_ERR_INV_VALUE);
783 if (!engine->ops->sign)
784 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
786 return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
787 use_textmode, include_certs, ctx);
792 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
795 return gpg_error (GPG_ERR_INV_VALUE);
797 if (!engine->ops->trustlist)
798 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
800 return (*engine->ops->trustlist) (engine->engine, pattern);
805 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
806 gpgme_data_t signed_text, gpgme_data_t plaintext)
809 return gpg_error (GPG_ERR_INV_VALUE);
811 if (!engine->ops->verify)
812 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
814 return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
819 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
823 return gpg_error (GPG_ERR_INV_VALUE);
825 if (!engine->ops->getauditlog)
826 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
828 return (*engine->ops->getauditlog) (engine->engine, output, flags);
833 _gpgme_engine_op_assuan_transact (engine_t engine,
835 gpgme_assuan_data_cb_t data_cb,
837 gpgme_assuan_inquire_cb_t inq_cb,
839 gpgme_assuan_status_cb_t status_cb,
840 void *status_cb_value)
843 return gpg_error (GPG_ERR_INV_VALUE);
845 if (!engine->ops->opassuan_transact)
846 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
848 return (*engine->ops->opassuan_transact) (engine->engine,
850 data_cb, data_cb_value,
851 inq_cb, inq_cb_value,
852 status_cb, status_cb_value);
857 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
860 return gpg_error (GPG_ERR_INV_VALUE);
862 if (!engine->ops->conf_load)
863 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
865 return (*engine->ops->conf_load) (engine->engine, conf_p);
870 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
873 return gpg_error (GPG_ERR_INV_VALUE);
875 if (!engine->ops->conf_save)
876 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
878 return (*engine->ops->conf_save) (engine->engine, conf);
883 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
888 (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
893 _gpgme_engine_io_event (engine_t engine,
894 gpgme_event_io_t type, void *type_data)
899 (*engine->ops->io_event) (engine->engine, type, type_data);
903 /* Cancel the session and the pending operation if any. */
905 _gpgme_engine_cancel (engine_t engine)
908 return gpg_error (GPG_ERR_INV_VALUE);
910 if (!engine->ops->cancel)
911 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
913 return (*engine->ops->cancel) (engine->engine);
917 /* Cancel the pending operation, but not the complete session. */
919 _gpgme_engine_cancel_op (engine_t engine)
922 return gpg_error (GPG_ERR_INV_VALUE);
924 if (!engine->ops->cancel_op)
927 return (*engine->ops->cancel_op) (engine->engine);
931 /* Change the passphrase for KEY. */
933 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
937 return gpg_error (GPG_ERR_INV_VALUE);
939 if (!engine->ops->passwd)
940 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
942 return (*engine->ops->passwd) (engine->engine, key, flags);
946 /* Set the pinentry mode for ENGINE to MODE. */
948 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
951 return gpg_error (GPG_ERR_INV_VALUE);
953 if (!engine->ops->set_pinentry_mode)
954 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
956 return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
961 _gpgme_engine_op_spawn (engine_t engine,
962 const char *file, const char *argv[],
964 gpgme_data_t dataout, gpgme_data_t dataerr,
968 return gpg_error (GPG_ERR_INV_VALUE);
970 if (!engine->ops->opspawn)
971 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
973 return (*engine->ops->opspawn) (engine->engine, file, argv,
974 datain, dataout, dataerr, flags);