gpgme/src/engine.c
Werner Koch a1f76b3b54
core: Add extended versions of the encrypt functions.
* src/gpgme.h.in (gpgme_op_encrypt_ext_start) New.
(gpgme_op_encrypt_ext): New.
(gpgme_op_encrypt_sign_ext_start): New.
(gpgme_op_encrypt_sign_ext): New.
* src/libgpgme.vers, tests/run-encrypt.c: Add them.

* src/encrypt.c (encrypt_start): Add arg recpstring.
(gpgme_op_encrypt): Factor code out to ...
(gpgme_op_encrypt_ext): new function with new arg recpstring.
(gpgme_op_encrypt_start): Factor code out to ...
(gpgme_op_encrypt_ext_start): new function with new arg recpstring.
* src/encrypt-sign.c (encrypt_sign_start): Add arg recpstring.
(gpgme_op_encrypt_sign): Factor code out to ...
(gpgme_op_encrypt_sign_ext): new function with new arg recpstring.
(gpgme_op_encrypt_sign_start): Factor code out to ...
(gpgme_op_encrypt_sign_ext_start): new function with new arg
recpstring.

* src/engine-backend.h (struct engine_ops): Change fields encrypt and
encrypt_sign.
* src/engine.c (_gpgme_engine_op_encrypt): Add arg recpstring and pass
to engine.
(_gpgme_engine_op_encrypt_sign): Ditto.
* src/engine-gpg.c (append_args_from_recipients_string): New.
(gpg_encrypt): Add arg recpstring and call new function as needed.
(gpg_encrypt_sign): Ditto.
* src/engine-gpgsm.c (set_recipients_from_string): New.
(gpgsm_encrypt): Add arg recpstring and call new function as needed.
* src/engine-uiserver.c (set_recipients_from_string): New.
(uiserver_encrypt): Add arg recpstring and call new function as
needed.

* tests/run-encrypt.c (xstrdup): New.
(main): Add option --keystring.

* src/gpgme-json.c (get_keys): Simplify.
(op_encrypt): Modify to make use of the extended encrypt function.

--

This new feature can be used to avoid the need for a key lookup and
thus several extra calls to the backend.

Note that run-test uses a semicolon as delimiter because that make
testing the feature on the command line much easier.

Signed-off-by: Werner Koch <wk@gnupg.org>
2018-04-17 08:45:00 +02:00

1132 lines
28 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* engine.c - GPGME engine support.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009, 2010 g10 Code GmbH
This file is part of GPGME.
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "gpgme.h"
#include "util.h"
#include "sema.h"
#include "ops.h"
#include "debug.h"
#include "engine.h"
#include "engine-backend.h"
struct engine
{
struct engine_ops *ops;
void *engine;
};
static struct engine_ops *engine_ops[] =
{
&_gpgme_engine_ops_gpg, /* OpenPGP. */
&_gpgme_engine_ops_gpgsm, /* CMS. */
&_gpgme_engine_ops_gpgconf, /* gpg-conf. */
&_gpgme_engine_ops_assuan, /* Low-Level Assuan. */
&_gpgme_engine_ops_g13, /* Crypto VFS. */
#ifdef ENABLE_UISERVER
&_gpgme_engine_ops_uiserver, /* UI-Server. */
#else
NULL,
#endif
&_gpgme_engine_ops_spawn
};
/* The engine info. */
static gpgme_engine_info_t engine_info;
DEFINE_STATIC_LOCK (engine_info_lock);
/* If non-NULL, the minimal version required for all engines. */
static char *engine_minimal_version;
/* Get the file name of the engine for PROTOCOL. */
static const char *
engine_get_file_name (gpgme_protocol_t proto)
{
if (proto > DIM (engine_ops))
return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_file_name)
return (*engine_ops[proto]->get_file_name) ();
else
return NULL;
}
/* Get the standard home dir of the engine for PROTOCOL. */
static const char *
engine_get_home_dir (gpgme_protocol_t proto)
{
if (proto > DIM (engine_ops))
return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
return (*engine_ops[proto]->get_home_dir) ();
else
return NULL;
}
/* Get a malloced string containing the version number of the engine
* for PROTOCOL. If this function returns NULL for a valid protocol,
* it should be assumed that the engine is a pseudo engine. */
static char *
engine_get_version (gpgme_protocol_t proto, const char *file_name)
{
if (proto > DIM (engine_ops))
return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_version)
return (*engine_ops[proto]->get_version) (file_name);
else
return NULL;
}
/* Get the required version number of the engine for PROTOCOL. This
* may be NULL. */
static const char *
engine_get_req_version (gpgme_protocol_t proto)
{
if (proto > DIM (engine_ops))
return NULL;
if (engine_ops[proto] && engine_ops[proto]->get_req_version)
return (*engine_ops[proto]->get_req_version) ();
else
return NULL;
}
/* Verify the version requirement for the engine for PROTOCOL. */
gpgme_error_t
gpgme_engine_check_version (gpgme_protocol_t proto)
{
gpgme_error_t err;
gpgme_engine_info_t info;
int result;
LOCK (engine_info_lock);
info = engine_info;
if (!info)
{
/* Make sure it is initialized. */
UNLOCK (engine_info_lock);
err = gpgme_get_engine_info (&info);
if (err)
return err;
LOCK (engine_info_lock);
}
while (info && info->protocol != proto)
info = info->next;
if (!info)
result = 0;
else
result = _gpgme_compare_versions (info->version,
info->req_version);
UNLOCK (engine_info_lock);
return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
}
/* Release the engine info INFO. */
void
_gpgme_engine_info_release (gpgme_engine_info_t info)
{
while (info)
{
gpgme_engine_info_t next_info = info->next;
if (info->file_name)
free (info->file_name);
if (info->home_dir)
free (info->home_dir);
if (info->version)
free (info->version);
free (info);
info = next_info;
}
}
/* This is an internal function to set a mimimal required version.
* This function must only be called by gpgme_set_global_flag.
* Returns 0 on success. */
int
_gpgme_set_engine_minimal_version (const char *value)
{
free (engine_minimal_version);
if (value)
{
engine_minimal_version = strdup (value);
return !engine_minimal_version;
}
else
{
engine_minimal_version = NULL;
return 0;
}
}
/* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. The
returned data is valid until the next gpgme_set_engine_info. */
gpgme_error_t
gpgme_get_engine_info (gpgme_engine_info_t *info)
{
gpgme_error_t err;
LOCK (engine_info_lock);
if (!engine_info)
{
gpgme_engine_info_t *lastp = &engine_info;
gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
GPGME_PROTOCOL_CMS,
GPGME_PROTOCOL_GPGCONF,
GPGME_PROTOCOL_ASSUAN,
GPGME_PROTOCOL_G13,
GPGME_PROTOCOL_UISERVER,
GPGME_PROTOCOL_SPAWN };
unsigned int proto;
err = 0;
for (proto = 0; proto < DIM (proto_list); proto++)
{
const char *ofile_name = engine_get_file_name (proto_list[proto]);
const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
char *version = engine_get_version (proto_list[proto], NULL);
char *file_name;
char *home_dir;
if (!ofile_name)
continue;
file_name = strdup (ofile_name);
if (!file_name)
err = gpg_error_from_syserror ();
if (ohome_dir)
{
home_dir = strdup (ohome_dir);
if (!home_dir && !err)
err = gpg_error_from_syserror ();
}
else
home_dir = NULL;
*lastp = calloc (1, sizeof (*engine_info));
if (!*lastp && !err)
err = gpg_error_from_syserror ();
/* Check against the optional minimal engine version. */
if (!err && version && engine_minimal_version
&& !_gpgme_compare_versions (version, engine_minimal_version))
{
#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
err = gpg_error (GPG_ERR_NO_ENGINE);
#else
err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
#endif
}
/* Now set the dummy version for pseudo engines. */
if (!err && !version)
{
version = strdup ("1.0.0");
if (!version)
err = gpg_error_from_syserror ();
}
if (err)
{
_gpgme_engine_info_release (engine_info);
engine_info = NULL;
if (file_name)
free (file_name);
if (home_dir)
free (home_dir);
if (version)
free (version);
UNLOCK (engine_info_lock);
return err;
}
(*lastp)->protocol = proto_list[proto];
(*lastp)->file_name = file_name;
(*lastp)->home_dir = home_dir;
(*lastp)->version = version;
(*lastp)->req_version = engine_get_req_version (proto_list[proto]);
if (!(*lastp)->req_version)
(*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
(*lastp)->next = NULL;
lastp = &(*lastp)->next;
}
}
*info = engine_info;
UNLOCK (engine_info_lock);
return 0;
}
/* Get a deep copy of the engine info and return it in INFO. */
gpgme_error_t
_gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
{
gpgme_error_t err = 0;
gpgme_engine_info_t info;
gpgme_engine_info_t new_info;
gpgme_engine_info_t *lastp;
LOCK (engine_info_lock);
info = engine_info;
if (!info)
{
/* Make sure it is initialized. */
UNLOCK (engine_info_lock);
err = gpgme_get_engine_info (&info);
if (err)
return err;
LOCK (engine_info_lock);
}
new_info = NULL;
lastp = &new_info;
while (info)
{
char *file_name;
char *home_dir;
char *version;
assert (info->file_name);
file_name = strdup (info->file_name);
if (!file_name)
err = gpg_error_from_syserror ();
if (info->home_dir)
{
home_dir = strdup (info->home_dir);
if (!home_dir && !err)
err = gpg_error_from_syserror ();
}
else
home_dir = NULL;
if (info->version)
{
version = strdup (info->version);
if (!version && !err)
err = gpg_error_from_syserror ();
}
else
version = NULL;
*lastp = malloc (sizeof (*engine_info));
if (!*lastp && !err)
err = gpg_error_from_syserror ();
if (err)
{
_gpgme_engine_info_release (new_info);
if (file_name)
free (file_name);
if (home_dir)
free (home_dir);
if (version)
free (version);
UNLOCK (engine_info_lock);
return err;
}
(*lastp)->protocol = info->protocol;
(*lastp)->file_name = file_name;
(*lastp)->home_dir = home_dir;
(*lastp)->version = version;
(*lastp)->req_version = info->req_version;
(*lastp)->next = NULL;
lastp = &(*lastp)->next;
info = info->next;
}
*r_info = new_info;
UNLOCK (engine_info_lock);
return 0;
}
/* Set the engine info for the info list INFO, protocol PROTO, to the
file name FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t
_gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
const char *file_name, const char *home_dir)
{
char *new_file_name;
char *new_home_dir;
char *new_version;
/* FIXME: Use some PROTO_MAX definition. */
if (proto > DIM (engine_ops))
return gpg_error (GPG_ERR_INV_VALUE);
while (info && info->protocol != proto)
info = info->next;
if (!info)
return trace_gpg_error (GPG_ERR_INV_ENGINE);
/* Prepare new members. */
if (file_name)
new_file_name = strdup (file_name);
else
{
const char *ofile_name = engine_get_file_name (proto);
assert (ofile_name);
new_file_name = strdup (ofile_name);
}
if (!new_file_name)
return gpg_error_from_syserror ();
if (home_dir)
{
new_home_dir = strdup (home_dir);
if (!new_home_dir)
{
free (new_file_name);
return gpg_error_from_syserror ();
}
}
else
{
const char *ohome_dir = engine_get_home_dir (proto);
if (ohome_dir)
{
new_home_dir = strdup (ohome_dir);
if (!new_home_dir)
{
free (new_file_name);
return gpg_error_from_syserror ();
}
}
else
new_home_dir = NULL;
}
new_version = engine_get_version (proto, new_file_name);
if (!new_version)
{
new_version = strdup ("1.0.0"); /* Fake one for dummy entries. */
if (!new_version)
{
free (new_file_name);
free (new_home_dir);
}
}
/* Remove the old members. */
assert (info->file_name);
free (info->file_name);
if (info->home_dir)
free (info->home_dir);
if (info->version)
free (info->version);
/* Install the new members. */
info->file_name = new_file_name;
info->home_dir = new_home_dir;
info->version = new_version;
return 0;
}
/* Set the default engine info for the protocol PROTO to the file name
FILE_NAME and the home directory HOME_DIR. */
gpgme_error_t
gpgme_set_engine_info (gpgme_protocol_t proto,
const char *file_name, const char *home_dir)
{
gpgme_error_t err;
gpgme_engine_info_t info;
LOCK (engine_info_lock);
info = engine_info;
if (!info)
{
/* Make sure it is initialized. */
UNLOCK (engine_info_lock);
err = gpgme_get_engine_info (&info);
if (err)
return err;
LOCK (engine_info_lock);
}
err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
UNLOCK (engine_info_lock);
return err;
}
gpgme_error_t
_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
{
engine_t engine;
if (!info->file_name || !info->version)
return trace_gpg_error (GPG_ERR_INV_ENGINE);
engine = calloc (1, sizeof *engine);
if (!engine)
return gpg_error_from_syserror ();
engine->ops = engine_ops[info->protocol];
if (engine->ops->new)
{
gpgme_error_t err;
err = (*engine->ops->new) (&engine->engine,
info->file_name, info->home_dir,
info->version);
if (err)
{
free (engine);
return err;
}
}
else
engine->engine = NULL;
*r_engine = engine;
return 0;
}
gpgme_error_t
_gpgme_engine_reset (engine_t engine)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->reset)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->reset) (engine->engine);
}
void
_gpgme_engine_release (engine_t engine)
{
if (!engine)
return;
if (engine->ops->release)
(*engine->ops->release) (engine->engine);
free (engine);
}
/* Set a status callback which is used to monitor the status values
* before they are passed to a handler set with
* _gpgme_engine_set_status_handler. */
void
_gpgme_engine_set_status_cb (engine_t engine,
gpgme_status_cb_t cb, void *cb_value)
{
if (!engine)
return;
if (engine->ops->set_status_cb)
(*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
}
void
_gpgme_engine_set_status_handler (engine_t engine,
engine_status_handler_t fnc, void *fnc_value)
{
if (!engine)
return;
if (engine->ops->set_status_handler)
(*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
}
gpgme_error_t
_gpgme_engine_set_command_handler (engine_t engine,
engine_command_handler_t fnc,
void *fnc_value,
gpgme_data_t linked_data)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->set_command_handler)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->set_command_handler) (engine->engine,
fnc, fnc_value, linked_data);
}
gpgme_error_t
_gpgme_engine_set_colon_line_handler (engine_t engine,
engine_colon_line_handler_t fnc,
void *fnc_value)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->set_colon_line_handler)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->set_colon_line_handler) (engine->engine,
fnc, fnc_value);
}
gpgme_error_t
_gpgme_engine_set_locale (engine_t engine, int category,
const char *value)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->set_locale)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->set_locale) (engine->engine, category, value);
}
gpgme_error_t
_gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->set_protocol)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->set_protocol) (engine->engine, protocol);
}
/* Pass information about the current context to the engine. The
* engine may use this context to retrieve context specific flags.
* Important: The engine is required to immediately copy the required
* flags to its own context!
*
* This function will eventually be used to reduce the number of
* explicit passed flags. */
void
_gpgme_engine_set_engine_flags (engine_t engine, gpgme_ctx_t ctx)
{
if (!engine)
return;
if (!engine->ops->set_engine_flags)
return;
(*engine->ops->set_engine_flags) (engine->engine, ctx);
}
gpgme_error_t
_gpgme_engine_op_decrypt (engine_t engine,
gpgme_decrypt_flags_t flags,
gpgme_data_t ciph,
gpgme_data_t plain, int export_session_key,
const char *override_session_key,
int auto_key_retrieve)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->decrypt)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->decrypt) (engine->engine, flags, ciph, plain,
export_session_key, override_session_key,
auto_key_retrieve);
}
gpgme_error_t
_gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
unsigned int flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->delete)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->delete) (engine->engine, key, flags);
}
gpgme_error_t
_gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->edit)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
}
gpgme_error_t
_gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
const char *recpstring,
gpgme_encrypt_flags_t flags,
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->encrypt)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->encrypt) (engine->engine, recp, recpstring,
flags, plain, ciph, use_armor);
}
gpgme_error_t
_gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
const char *recpstring,
gpgme_encrypt_flags_t flags,
gpgme_data_t plain, gpgme_data_t ciph,
int use_armor, gpgme_ctx_t ctx /* FIXME */)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->encrypt_sign)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring,
flags, plain, ciph, use_armor, ctx);
}
gpgme_error_t
_gpgme_engine_op_export (engine_t engine, const char *pattern,
gpgme_export_mode_t mode, gpgme_data_t keydata,
int use_armor)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->export)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->export) (engine->engine, pattern, mode,
keydata, use_armor);
}
gpgme_error_t
_gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
unsigned int reserved, gpgme_data_t keydata,
int use_armor)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->export_ext)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
keydata, use_armor);
}
gpgme_error_t
_gpgme_engine_op_genkey (engine_t engine,
const char *userid, const char *algo,
unsigned long reserved, unsigned long expires,
gpgme_key_t key, unsigned int flags,
gpgme_data_t help_data,
unsigned int extraflags,
gpgme_data_t pubkey, gpgme_data_t seckey)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->genkey)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->genkey) (engine->engine,
userid, algo, reserved, expires, key, flags,
help_data, extraflags,
pubkey, seckey);
}
gpgme_error_t
_gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
unsigned long expires, unsigned int flags,
gpgme_ctx_t ctx)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->keysign)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->keysign) (engine->engine,
key, userid, expires, flags, ctx);
}
gpgme_error_t
_gpgme_engine_op_tofu_policy (engine_t engine,
gpgme_key_t key, gpgme_tofu_policy_t policy)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->tofu_policy)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->tofu_policy) (engine->engine, key, policy);
}
gpgme_error_t
_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
gpgme_key_t *keyarray)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->import)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->import) (engine->engine, keydata, keyarray);
}
gpgme_error_t
_gpgme_engine_op_keylist (engine_t engine, const char *pattern,
int secret_only, gpgme_keylist_mode_t mode,
int engine_flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->keylist)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
engine_flags);
}
gpgme_error_t
_gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
int secret_only, int reserved,
gpgme_keylist_mode_t mode, int engine_flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->keylist_ext)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
reserved, mode, engine_flags);
}
gpgme_error_t
_gpgme_engine_op_keylist_data (engine_t engine, gpgme_data_t data)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->keylist_data)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->keylist_data) (engine->engine, data);
}
gpgme_error_t
_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor,
int use_textmode, int include_certs,
gpgme_ctx_t ctx /* FIXME */)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->sign)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
use_textmode, include_certs, ctx);
}
gpgme_error_t
_gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->trustlist)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->trustlist) (engine->engine, pattern);
}
gpgme_error_t
_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->verify)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
ctx);
}
gpgme_error_t
_gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
unsigned int flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->getauditlog)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->getauditlog) (engine->engine, output, flags);
}
gpgme_error_t
_gpgme_engine_op_assuan_transact (engine_t engine,
const char *command,
gpgme_assuan_data_cb_t data_cb,
void *data_cb_value,
gpgme_assuan_inquire_cb_t inq_cb,
void *inq_cb_value,
gpgme_assuan_status_cb_t status_cb,
void *status_cb_value)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->opassuan_transact)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->opassuan_transact) (engine->engine,
command,
data_cb, data_cb_value,
inq_cb, inq_cb_value,
status_cb, status_cb_value);
}
gpgme_error_t
_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->conf_load)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->conf_load) (engine->engine, conf_p);
}
gpgme_error_t
_gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->conf_save)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->conf_save) (engine->engine, conf);
}
gpgme_error_t
_gpgme_engine_op_conf_dir (engine_t engine, const char *what, char **result)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->conf_dir)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->conf_dir) (engine->engine, what, result);
}
gpgme_error_t
_gpgme_engine_op_query_swdb (engine_t engine,
const char *name, const char *iversion,
gpgme_query_swdb_result_t result)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->query_swdb)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
}
void
_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
{
if (!engine)
return;
(*engine->ops->set_io_cbs) (engine->engine, io_cbs);
}
void
_gpgme_engine_io_event (engine_t engine,
gpgme_event_io_t type, void *type_data)
{
if (!engine)
return;
(*engine->ops->io_event) (engine->engine, type, type_data);
}
/* Cancel the session and the pending operation if any. */
gpgme_error_t
_gpgme_engine_cancel (engine_t engine)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->cancel)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->cancel) (engine->engine);
}
/* Cancel the pending operation, but not the complete session. */
gpgme_error_t
_gpgme_engine_cancel_op (engine_t engine)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->cancel_op)
return 0;
return (*engine->ops->cancel_op) (engine->engine);
}
/* Change the passphrase for KEY. */
gpgme_error_t
_gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
unsigned int flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->passwd)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->passwd) (engine->engine, key, flags);
}
/* Set the pinentry mode for ENGINE to MODE. */
gpgme_error_t
_gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->set_pinentry_mode)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
}
gpgme_error_t
_gpgme_engine_op_spawn (engine_t engine,
const char *file, const char *argv[],
gpgme_data_t datain,
gpgme_data_t dataout, gpgme_data_t dataerr,
unsigned int flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
if (!engine->ops->opspawn)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->opspawn) (engine->engine, file, argv,
datain, dataout, dataerr, flags);
}