diff options
Diffstat (limited to 'src/engine.c')
-rw-r--r-- | src/engine.c | 138 |
1 files changed, 126 insertions, 12 deletions
diff --git a/src/engine.c b/src/engine.c index 8e84da9..a1173a0 100644 --- a/src/engine.c +++ b/src/engine.c @@ -63,6 +63,10 @@ static struct engine_ops *engine_ops[] = 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 * @@ -93,7 +97,8 @@ engine_get_home_dir (gpgme_protocol_t proto) /* Get a malloced string containing the version number of the engine - for PROTOCOL. */ + * 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) { @@ -107,7 +112,8 @@ engine_get_version (gpgme_protocol_t proto, const char *file_name) } -/* Get the required version number of the engine for PROTOCOL. */ +/* 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) { @@ -164,8 +170,8 @@ _gpgme_engine_info_release (gpgme_engine_info_t info) { gpgme_engine_info_t next_info = info->next; - assert (info->file_name); - free (info->file_name); + if (info->file_name) + free (info->file_name); if (info->home_dir) free (info->home_dir); if (info->version) @@ -176,6 +182,26 @@ _gpgme_engine_info_release (gpgme_engine_info_t 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 @@ -203,6 +229,7 @@ gpgme_get_engine_info (gpgme_engine_info_t *info) { 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; @@ -222,10 +249,29 @@ gpgme_get_engine_info (gpgme_engine_info_t *info) else home_dir = NULL; - *lastp = malloc (sizeof (*engine_info)); + *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); @@ -235,6 +281,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info) free (file_name); if (home_dir) free (home_dir); + if (version) + free (version); UNLOCK (engine_info_lock); return err; @@ -243,8 +291,10 @@ gpgme_get_engine_info (gpgme_engine_info_t *info) (*lastp)->protocol = proto_list[proto]; (*lastp)->file_name = file_name; (*lastp)->home_dir = home_dir; - (*lastp)->version = engine_get_version (proto_list[proto], NULL); + (*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; } @@ -353,6 +403,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto, { char *new_file_name; char *new_home_dir; + char *new_version; /* FIXME: Use some PROTO_MAX definition. */ if (proto > DIM (engine_ops)) @@ -401,6 +452,17 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto, 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); @@ -412,7 +474,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto, /* Install the new members. */ info->file_name = new_file_name; info->home_dir = new_home_dir; - info->version = engine_get_version (proto, new_file_name); + info->version = new_version; return 0; } @@ -463,7 +525,8 @@ _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine) { gpgme_error_t err; err = (*engine->ops->new) (&engine->engine, - info->file_name, info->home_dir); + info->file_name, info->home_dir, + info->version); if (err) { free (engine); @@ -503,6 +566,21 @@ _gpgme_engine_release (engine_t 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) @@ -695,9 +773,13 @@ _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[], gpgme_error_t -_gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data, - int use_armor, gpgme_data_t pubkey, - gpgme_data_t seckey) +_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); @@ -705,12 +787,44 @@ _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data, if (!engine->ops->genkey) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->genkey) (engine->engine, help_data, use_armor, + 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) { |