diff --git a/src/context.h b/src/context.h index 076d0731..7333d2d5 100644 --- a/src/context.h +++ b/src/context.h @@ -1,202 +1,216 @@ /* context.h - Definitions for a GPGME context. Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004, 2005, 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 . */ #ifndef CONTEXT_H #define CONTEXT_H #include #include "gpgme.h" #include "engine.h" #include "wait.h" #include "sema.h" extern gpgme_error_t _gpgme_selftest; /* Operations might require to remember arbitrary information and data objects during invocations of the status handler. The ctx_op_data structure provides a generic framework to hook in such additional data. */ typedef enum { OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE, OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT, OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT, OPDATA_PASSWD, OPDATA_EXPORT, OPDATA_KEYSIGN, OPDATA_TOFU_POLICY, OPDATA_QUERY_SWDB } ctx_op_data_id_t; /* "gpgmeres" in ASCII. */ #define CTX_OP_DATA_MAGIC 0x736572656d677067ULL struct ctx_op_data { /* A magic word just to make sure people don't deallocate something that ain't a result structure. */ unsigned long long magic; /* The next element in the linked list, or NULL if this is the last element. Used by op data structures linked into a context. */ struct ctx_op_data *next; /* The type of the hook data, which can be used by a routine to lookup the hook data. */ ctx_op_data_id_t type; /* The function to release HOOK and all its associated resources. Can be NULL if no special deallocation routine is necessary. */ void (*cleanup) (void *hook); /* The hook that points to the operation data. */ void *hook; /* The number of outstanding references. */ int references; }; typedef struct ctx_op_data *ctx_op_data_t; + /* The context defines an environment in which crypto operations can - be performed (sequentially). */ + * be performed (sequentially). */ struct gpgme_context { DECLARE_LOCK (lock); /* The unique serial number of this context object. This is used * for a weak reference of the context. Using the address of the * context is not always possible becuase it might have already been * freed and reused. */ uint64_t serial; + /* A link to the next context. We keep all contex object in the + * linked list to so that we are abale to find a context by its + * serial number. */ + gpgme_ctx_t next_ctx; + /* True if the context was canceled asynchronously. */ int canceled; /* The engine info for this context. */ gpgme_engine_info_t engine_info; /* The protocol used by this context. */ gpgme_protocol_t protocol; /* The running engine process. */ engine_t engine; /* Engine's sub protocol. */ gpgme_protocol_t sub_protocol; /* True if armor mode should be used. */ unsigned int use_armor : 1; /* True if text mode should be used. */ unsigned int use_textmode : 1; /* True if offline mode should be used. */ unsigned int offline : 1; /* True if a status callback shall be called for nearly all status * lines. */ unsigned int full_status : 1; /* The Tofu info has a human readable string which is presented to * the user in a directly usable format. By enabling this flag the * unmodified string, as received form gpg, will be returned. */ unsigned int raw_description : 1; /* True if session keys should be exported upon decryption. */ unsigned int export_session_keys : 1; /* True if a Pinentry was launched during the last operation. This * flag is cleared with each operation. */ unsigned int redraw_suggested : 1; /* True if the option --auto-key-retrieve shall be passed to gpg. */ unsigned int auto_key_retrieve : 1; /* Do not use the symmtric encryption passphrase cache. */ unsigned int no_symkey_cache : 1; /* Pass --ignore-mdc-error to gpg. Note that this flag is reset * after the operation. */ unsigned int ignore_mdc_error : 1; /* Flags for keylist mode. */ gpgme_keylist_mode_t keylist_mode; /* The current pinentry mode. */ gpgme_pinentry_mode_t pinentry_mode; /* Number of certs to be included. */ unsigned int include_certs; /* The actual number of keys in SIGNERS, the allocated size of the * array, and the array with the signing keys. */ unsigned int signers_len; unsigned int signers_size; gpgme_key_t *signers; /* The signature notations for this context. */ gpgme_sig_notation_t sig_notations; /* The sender's addr-spec or NULL. */ char *sender; /* The gpg specific override session key or NULL. */ char *override_session_key; /* The optional request origin. */ char *request_origin; /* The optional auto key locate options. */ char *auto_key_locate; /* The locale for the pinentry. */ char *lc_ctype; char *lc_messages; /* The optional trust-model override. */ char *trust_model; /* The operation data hooked into the context. */ ctx_op_data_t op_data; /* The user provided passphrase callback and its hook value. */ gpgme_passphrase_cb_t passphrase_cb; void *passphrase_cb_value; /* The user provided progress callback and its hook value. */ gpgme_progress_cb_t progress_cb; void *progress_cb_value; /* The user provided status callback and its hook value. */ gpgme_status_cb_t status_cb; void *status_cb_value; /* A list of file descriptors in active use by the current operation. */ struct fd_table fdt; struct gpgme_io_cbs io_cbs; }; /* Macro to retrieve the serial number. Returns 0 if CTX is NULL. */ #define CTXSERIAL(ctx) (ctx? (unsigned long)ctx->serial : 0) +/*-- gpgme.c --*/ + +gpg_error_t _gpgme_get_ctx (uint64_t serial, gpgme_ctx_t *r_ctx); + +gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err, + gpg_error_t op_err); + + #endif /* CONTEXT_H */ diff --git a/src/gpgme.c b/src/gpgme.c index 53189aa7..283290f4 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -1,1320 +1,1383 @@ /* gpgme.c - GnuPG Made Easy. * Copyright (C) 2000 Werner Koch (dd9jn) * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2012, - * 2014, 2015 g10 Code GmbH + * 2014, 2015, 2019 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 . * SPDX-License-Identifier: LGPL-2.1-or-later */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include #ifdef HAVE_LOCALE_H #include #endif #include "util.h" #include "context.h" #include "ops.h" #include "wait.h" #include "debug.h" #include "priv-io.h" #include "sys-util.h" #include "mbox-util.h" -/* The default locale and its lock. This lock is also used for the - * context serial number. */ -DEFINE_STATIC_LOCK (def_lc_lock); +/* The lock used to protect access to the default locale, the global + * serial counter, and the list of context objects. */ +DEFINE_STATIC_LOCK (context_list_lock); + +/* The default locale. Access is protected by CONTEXT_LIST_LOCK. */ static char *def_lc_ctype; static char *def_lc_messages; /* A serial number to identify a context. To make debugging easier by * distinguishing this from the data object s/n we initialize it with * an arbitrary offset. Debug output of this should be done using - * decimal notation. Updates are protected by the DEF_LC_LOCK. */ + * decimal notation. Updates are protected by CONTEXT_LIST_LOCK. */ static uint64_t last_ctx_serial = 200000; +/* A linked list of all context objects. Protected by + * CONTEXT_LIST_LOCK. */ +static gpgme_ctx_t context_list; - gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL; /* Protects all reference counters in result structures. All other - accesses to a result structure are read only. */ + * accesses to a result structure are read only. */ DEFINE_STATIC_LOCK (result_ref_lock); + + /* Set the global flag NAME to VALUE. Return 0 on success. Note that this function does not use gpgme_error and thus a non-zero return value merely means "error". Certain flags may be set before gpgme_check_version is called. See the manual for a description of supported flags. The caller must assure that this function is called only by one thread at a time. */ int gpgme_set_global_flag (const char *name, const char *value) { if (!name || !value) return -1; else if (!strcmp (name, "debug")) return _gpgme_debug_set_debug_envvar (value); else if (!strcmp (name, "disable-gpgconf")) { _gpgme_dirinfo_disable_gpgconf (); return 0; } else if (!strcmp (name, "require-gnupg")) return _gpgme_set_engine_minimal_version (value); else if (!strcmp (name, "gpgconf-name")) return _gpgme_set_default_gpgconf_name (value); else if (!strcmp (name, "gpg-name")) return _gpgme_set_default_gpg_name (value); else if (!strcmp (name, "w32-inst-dir")) return _gpgme_set_override_inst_dir (value); else return -1; } /* Create a new context as an environment for GPGME crypto operations. */ gpgme_error_t gpgme_new (gpgme_ctx_t *r_ctx) { gpgme_error_t err; gpgme_ctx_t ctx; TRACE_BEG (DEBUG_CTX, "gpgme_new", NULL, ""); if (_gpgme_selftest) return TRACE_ERR (_gpgme_selftest); if (!r_ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); ctx = calloc (1, sizeof *ctx); if (!ctx) return TRACE_ERR (gpg_error_from_syserror ()); INIT_LOCK (ctx->lock); err = _gpgme_engine_info_copy (&ctx->engine_info); if (!err && !ctx->engine_info) err = gpg_error (GPG_ERR_NO_ENGINE); if (err) { free (ctx); return TRACE_ERR (err); } ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL; ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT; ctx->protocol = GPGME_PROTOCOL_OpenPGP; ctx->sub_protocol = GPGME_PROTOCOL_DEFAULT; _gpgme_fd_table_init (&ctx->fdt); - LOCK (def_lc_lock); + LOCK (context_list_lock); if (def_lc_ctype) { ctx->lc_ctype = strdup (def_lc_ctype); if (!ctx->lc_ctype) { int saved_err = gpg_error_from_syserror (); - UNLOCK (def_lc_lock); + UNLOCK (context_list_lock); _gpgme_engine_info_release (ctx->engine_info); free (ctx); return TRACE_ERR (saved_err); } } else def_lc_ctype = NULL; if (def_lc_messages) { ctx->lc_messages = strdup (def_lc_messages); if (!ctx->lc_messages) { int saved_err = gpg_error_from_syserror (); - UNLOCK (def_lc_lock); + UNLOCK (context_list_lock); if (ctx->lc_ctype) free (ctx->lc_ctype); _gpgme_engine_info_release (ctx->engine_info); free (ctx); return TRACE_ERR (saved_err); } } else def_lc_messages = NULL; ctx->serial = ++last_ctx_serial; - UNLOCK (def_lc_lock); + /* Put the object itno a list. */ + ctx->next_ctx = context_list; + context_list = ctx; + + UNLOCK (context_list_lock); *r_ctx = ctx; TRACE_SUC ("ctx=%lu (%p)", CTXSERIAL(ctx), ctx); return 0; } +/* Check the status of the context described by SERIAL. + * Returns: + * 0 - All fine + * GPG_ERR_CANCELED - Context operation has been canceled. + * GPG_ERR_NO_OBJ - Context ist not anymore known. + * If R_CTX is not NULl and the context exists, it is stored there. + */ +gpg_error_t +_gpgme_get_ctx (uint64_t serial, gpgme_ctx_t *r_ctx) +{ + gpg_error_t err; + gpgme_ctx_t ctx = NULL; + + LOCK (context_list_lock); + for (ctx = context_list; ctx; ctx = ctx->next_ctx) + if (ctx->serial == serial) + break; + UNLOCK (context_list_lock); + if (ctx) + { + /* FIXME: The lock is only used for the canceled flag. We + * should remove it and rely on the global + * context_list_lock. */ + LOCK (ctx->lock); + err = ctx->canceled? gpg_error (GPG_ERR_CANCELED) : 0; + UNLOCK (ctx->lock); + } + else + err = gpg_error (GPG_ERR_NO_OBJ); + if (r_ctx) + *r_ctx = ctx; + return err; +} gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err, gpg_error_t op_err) { gpgme_error_t err; struct gpgme_io_event_done_data data; TRACE_BEG (DEBUG_CTX, "_gpgme_cancel_with_err", NULL, "ctx=%lu ctx_err=%i op_err=%i", CTXSERIAL (ctx), ctx_err, op_err); if (ctx_err) { err = _gpgme_engine_cancel (ctx->engine); if (err) return TRACE_ERR (err); } else { err = _gpgme_engine_cancel_op (ctx->engine); if (err) return TRACE_ERR (err); } data.err = ctx_err; data.op_err = op_err; _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data); return TRACE_ERR (0); } /* Cancel a pending asynchronous operation. */ gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx) { gpg_error_t err; TRACE_BEG (DEBUG_CTX, "gpgme_cancel", NULL, "ctx=%lu", CTXSERIAL (ctx)); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); err = _gpgme_cancel_with_err (ctx, gpg_error (GPG_ERR_CANCELED), 0); return TRACE_ERR (err); } /* Cancel a pending operation asynchronously. */ gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx) { TRACE_BEG (DEBUG_CTX, "gpgme_cancel_async", NULL, "ctx=%lu", CTXSERIAL (ctx)); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); LOCK (ctx->lock); ctx->canceled = 1; UNLOCK (ctx->lock); return TRACE_ERR (0); } /* Release all resources associated with the given context. */ void gpgme_release (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_release", NULL, "ctx=%lu", CTXSERIAL (ctx)); if (!ctx) return; + LOCK (context_list_lock); + if (context_list == ctx) + { + context_list = ctx->next_ctx; + ctx->next_ctx = NULL; + } + else + { + gpgme_ctx_t tmpctx; + + for (tmpctx = context_list; tmpctx; tmpctx = tmpctx->next_ctx) + if (tmpctx->next_ctx == ctx) + { + tmpctx->next_ctx = ctx->next_ctx; + ctx->next_ctx = NULL; + break; + } + } + UNLOCK (context_list_lock); + _gpgme_engine_release (ctx->engine); ctx->engine = NULL; _gpgme_fd_table_deinit (&ctx->fdt); _gpgme_release_result (ctx); _gpgme_signers_clear (ctx); _gpgme_sig_notation_clear (ctx); free (ctx->sender); free (ctx->signers); free (ctx->lc_ctype); free (ctx->lc_messages); free (ctx->override_session_key); free (ctx->request_origin); free (ctx->auto_key_locate); free (ctx->trust_model); _gpgme_engine_info_release (ctx->engine_info); ctx->engine_info = NULL; DESTROY_LOCK (ctx->lock); free (ctx); } void gpgme_result_ref (void *result) { struct ctx_op_data *data; if (! result) return; data = (void*)((char*)result - sizeof (struct ctx_op_data)); assert (data->magic == CTX_OP_DATA_MAGIC); LOCK (result_ref_lock); data->references++; UNLOCK (result_ref_lock); } void gpgme_result_unref (void *result) { struct ctx_op_data *data; if (! result) return; data = (void*)((char*)result - sizeof (struct ctx_op_data)); assert (data->magic == CTX_OP_DATA_MAGIC); LOCK (result_ref_lock); if (--data->references) { UNLOCK (result_ref_lock); return; } UNLOCK (result_ref_lock); if (data->cleanup) (*data->cleanup) (data->hook); free (data); } void _gpgme_release_result (gpgme_ctx_t ctx) { struct ctx_op_data *data = ctx->op_data; while (data) { struct ctx_op_data *next_data = data->next; data->next = NULL; gpgme_result_unref (data->hook); data = next_data; } ctx->op_data = NULL; } /* Note that setting the protocol will intentionally not fail if the * engine is not available. */ gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol) { TRACE_BEG (DEBUG_CTX, "gpgme_set_protocol", NULL, "ctx=%lu protocol=%i (%s)", CTXSERIAL (ctx), protocol, gpgme_get_protocol_name (protocol) ? gpgme_get_protocol_name (protocol) : "invalid"); if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS && protocol != GPGME_PROTOCOL_GPGCONF && protocol != GPGME_PROTOCOL_ASSUAN && protocol != GPGME_PROTOCOL_G13 && protocol != GPGME_PROTOCOL_UISERVER && protocol != GPGME_PROTOCOL_SPAWN) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (ctx->protocol != protocol) { /* Shut down the engine when switching protocols. */ if (ctx->engine) { TRACE_LOG ("releasing ctx->engine=%p", ctx->engine); _gpgme_engine_release (ctx->engine); ctx->engine = NULL; } ctx->protocol = protocol; } return TRACE_ERR (0); } gpgme_protocol_t gpgme_get_protocol (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_protocol", NULL, "ctx=%lu protocol=%i (%s)", CTXSERIAL (ctx), ctx->protocol, gpgme_get_protocol_name (ctx->protocol) ? gpgme_get_protocol_name (ctx->protocol) : "invalid"); return ctx->protocol; } gpgme_error_t gpgme_set_sub_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol) { TRACE (DEBUG_CTX, "gpgme_set_sub_protocol", NULL, "ctx=%lu protocol=%i (%s)", CTXSERIAL (ctx), protocol, gpgme_get_protocol_name (protocol) ? gpgme_get_protocol_name (protocol) : "invalid"); if (!ctx) return gpg_error (GPG_ERR_INV_VALUE); ctx->sub_protocol = protocol; return 0; } gpgme_protocol_t gpgme_get_sub_protocol (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_sub_protocol", NULL, "ctx=%lu sub_protocol=%i (%s)", CTXSERIAL (ctx), ctx->sub_protocol, gpgme_get_protocol_name (ctx->sub_protocol) ? gpgme_get_protocol_name (ctx->sub_protocol) : "invalid"); return ctx->sub_protocol; } const char * gpgme_get_protocol_name (gpgme_protocol_t protocol) { switch (protocol) { case GPGME_PROTOCOL_OpenPGP: return "OpenPGP"; case GPGME_PROTOCOL_CMS: return "CMS"; case GPGME_PROTOCOL_GPGCONF: return "GPGCONF"; case GPGME_PROTOCOL_ASSUAN: return "Assuan"; case GPGME_PROTOCOL_G13: return "G13"; case GPGME_PROTOCOL_UISERVER: return "UIServer"; case GPGME_PROTOCOL_SPAWN: return "Spawn"; case GPGME_PROTOCOL_DEFAULT: return "default"; case GPGME_PROTOCOL_UNKNOWN: return "unknown"; default: return NULL; } } /* Store the sender's address in the context. ADDRESS is addr-spec of * mailbox but my also be a complete mailbox, in which case this * function extracts the addr-spec from it. Returns 0 on success or * an error code if no valid addr-spec could be extracted from * ADDRESS. */ gpgme_error_t gpgme_set_sender (gpgme_ctx_t ctx, const char *address) { char *p = NULL; TRACE_BEG (DEBUG_CTX, "gpgme_set_sender", NULL, "ctx=%lu sender='%s'", CTXSERIAL (ctx), address?address:"(null)"); if (!ctx || (address && !(p = _gpgme_mailbox_from_userid (address)))) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); free (ctx->sender); ctx->sender = p; return TRACE_ERR (0); } /* Return the sender's address (addr-spec part) from the context or * NULL if none was set. The returned value is valid as long as the * CTX is valid and gpgme_set_sender has not been used. */ const char * gpgme_get_sender (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_sender", NULL, "ctx=%lu sender='%s'", CTXSERIAL (ctx), ctx?ctx->sender:""); return ctx->sender; } /* Enable or disable the use of an ascii armor for all output. */ void gpgme_set_armor (gpgme_ctx_t ctx, int use_armor) { TRACE (DEBUG_CTX, "gpgme_set_armor", NULL, "ctx=%lu use_armor=%i (%s)", CTXSERIAL (ctx), use_armor, use_armor ? "yes" : "no"); if (!ctx) return; ctx->use_armor = !!use_armor; } /* Return the state of the armor flag. */ int gpgme_get_armor (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_armor", NULL, "ctx=%lu use_armor=%i (%s)", CTXSERIAL (ctx), ctx->use_armor, ctx->use_armor ? "yes" : "no"); return ctx->use_armor; } /* Set the flag NAME for CTX to VALUE. Please consult the manual for * a description of the flags. */ gpgme_error_t gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value) { gpgme_error_t err = 0; int abool; TRACE (DEBUG_CTX, "gpgme_set_ctx_flag", NULL, "ctx=%lu name='%s' value='%s'", CTXSERIAL (ctx), name? name:"(null)", value?value:"(null)"); abool = (value && *value)? !!atoi (value) : 0; if (!ctx || !name || !value) err = gpg_error (GPG_ERR_INV_VALUE); else if (!strcmp (name, "redraw")) { ctx->redraw_suggested = abool; } else if (!strcmp (name, "full-status")) { ctx->full_status = abool; } else if (!strcmp (name, "raw-description")) { ctx->raw_description = abool; } else if (!strcmp (name, "export-session-key")) { ctx->export_session_keys = abool; } else if (!strcmp (name, "override-session-key")) { free (ctx->override_session_key); ctx->override_session_key = strdup (value); if (!ctx->override_session_key) err = gpg_error_from_syserror (); } else if (!strcmp (name, "auto-key-retrieve")) { ctx->auto_key_retrieve = abool; } else if (!strcmp (name, "request-origin")) { free (ctx->request_origin); ctx->request_origin = strdup (value); if (!ctx->request_origin) err = gpg_error_from_syserror (); } else if (!strcmp (name, "no-symkey-cache")) { ctx->no_symkey_cache = abool; } else if (!strcmp (name, "ignore-mdc-error")) { ctx->ignore_mdc_error = abool; } else if (!strcmp (name, "auto-key-locate")) { free (ctx->auto_key_locate); ctx->auto_key_locate = strdup (value); if (!ctx->auto_key_locate) err = gpg_error_from_syserror (); } else if (!strcmp (name, "trust-model")) { free (ctx->trust_model); ctx->trust_model = strdup (value); if (!ctx->trust_model) err = gpg_error_from_syserror (); } else err = gpg_error (GPG_ERR_UNKNOWN_NAME); return err; } /* Get the context flag named NAME. See gpgme_set_ctx_flag for a list * of valid names. If the NAME is unknown NULL is returned. For a * boolean flag an empty string is returned for False and the string * "1" for True; thus either atoi or a simple string test can be * used. */ const char * gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name) { if (!ctx || !name) return NULL; else if (!strcmp (name, "redraw")) { return ctx->redraw_suggested? "1":""; } else if (!strcmp (name, "full-status")) { return ctx->full_status? "1":""; } else if (!strcmp (name, "raw-description")) { return ctx->raw_description? "1":""; } else if (!strcmp (name, "export-session-key")) { return ctx->export_session_keys? "1":""; } else if (!strcmp (name, "override-session-key")) { return ctx->override_session_key? ctx->override_session_key : ""; } else if (!strcmp (name, "auto-key-retrieve")) { return ctx->auto_key_retrieve? "1":""; } else if (!strcmp (name, "request-origin")) { return ctx->request_origin? ctx->request_origin : ""; } else if (!strcmp (name, "no-symkey-cache")) { return ctx->no_symkey_cache? "1":""; } else if (!strcmp (name, "ignore-mdc-error")) { return ctx->ignore_mdc_error? "1":""; } else if (!strcmp (name, "auto-key-locate")) { return ctx->auto_key_locate? ctx->auto_key_locate : ""; } else return NULL; } /* Enable or disable the use of the special textmode. Textmode is for example used for the RFC2015 signatures; note that the updated RFC 3156 mandates that the MUA does some preparations so that textmode is not needed anymore. */ void gpgme_set_textmode (gpgme_ctx_t ctx, int use_textmode) { TRACE (DEBUG_CTX, "gpgme_set_textmode", NULL, "ctx=%lu use_textmode=%i (%s)", CTXSERIAL (ctx), use_textmode, use_textmode ? "yes" : "no"); if (!ctx) return; ctx->use_textmode = !!use_textmode; } /* Return the state of the textmode flag. */ int gpgme_get_textmode (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_textmode", NULL, "ctx=%lu use_textmode=%i (%s)", CTXSERIAL (ctx), ctx->use_textmode, ctx->use_textmode ? "yes" : "no"); return ctx->use_textmode; } /* Enable offline mode for this context. In offline mode dirmngr will be disabled. */ void gpgme_set_offline (gpgme_ctx_t ctx, int offline) { TRACE (DEBUG_CTX, "gpgme_set_offline", NULL, "ctx=%lu offline=%i (%s)", CTXSERIAL (ctx), offline, offline ? "yes" : "no"); if (!ctx) return; ctx->offline = !!offline; } /* Return the state of the offline flag. */ int gpgme_get_offline (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_offline", NULL, "ctx=%lu offline=%i (%s)", CTXSERIAL (ctx), ctx->offline, ctx->offline ? "yes" : "no"); return ctx->offline; } /* Set the number of certifications to include in an S/MIME message. The default is GPGME_INCLUDE_CERTS_DEFAULT. -1 means all certs, and -2 means all certs except the root cert. */ void gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs) { if (!ctx) return; if (nr_of_certs == GPGME_INCLUDE_CERTS_DEFAULT) ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT; else if (nr_of_certs < -2) ctx->include_certs = -2; else ctx->include_certs = nr_of_certs; TRACE (DEBUG_CTX, "gpgme_set_include_certs", NULL, "ctx=%lu nr_of_certs=%i%s", CTXSERIAL (ctx), nr_of_certs, nr_of_certs == ctx->include_certs ? "" : " (-2)"); } /* Get the number of certifications to include in an S/MIME message. */ int gpgme_get_include_certs (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_include_certs", NULL, "ctx=%lu include_certs=%i", CTXSERIAL (ctx), ctx->include_certs); return ctx->include_certs; } /* This function changes the default behaviour of the keylisting functions. MODE is a bitwise-OR of the GPGME_KEYLIST_* flags. The default mode is GPGME_KEYLIST_MODE_LOCAL. */ gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode) { TRACE (DEBUG_CTX, "gpgme_set_keylist_mode", NULL, "ctx=%lu keylist_mode=0x%x", CTXSERIAL (ctx), mode); if (!ctx) return gpg_error (GPG_ERR_INV_VALUE); ctx->keylist_mode = mode; return 0; } /* This function returns the default behaviour of the keylisting functions. */ gpgme_keylist_mode_t gpgme_get_keylist_mode (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_keylist_mode", NULL, "ctx=%lu keylist_mode=0x%x", CTXSERIAL (ctx), ctx->keylist_mode); return ctx->keylist_mode; } /* Set the pinentry mode for CTX to MODE. */ gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_pinentry_mode_t mode) { TRACE (DEBUG_CTX, "gpgme_set_pinentry_mode", NULL, "ctx=%lu pinentry_mode=%u", CTXSERIAL (ctx), (unsigned int)mode); if (!ctx) return gpg_error (GPG_ERR_INV_VALUE); switch (mode) { case GPGME_PINENTRY_MODE_DEFAULT: case GPGME_PINENTRY_MODE_ASK: case GPGME_PINENTRY_MODE_CANCEL: case GPGME_PINENTRY_MODE_ERROR: case GPGME_PINENTRY_MODE_LOOPBACK: break; default: return gpg_error (GPG_ERR_INV_VALUE); } ctx->pinentry_mode = mode; return 0; } /* Get the pinentry mode of CTX. */ gpgme_pinentry_mode_t gpgme_get_pinentry_mode (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_get_pinentry_mode", NULL, "ctx=%lu pinentry_mode=%u", CTXSERIAL (ctx), (unsigned int)ctx->pinentry_mode); return ctx->pinentry_mode; } /* This function sets a callback function to be used to pass a passphrase to gpg. */ void gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, void *cb_value) { TRACE (DEBUG_CTX, "gpgme_set_passphrase_cb", NULL, "ctx=%lu passphrase_cb=%p/%p", CTXSERIAL (ctx), cb, cb_value); if (!ctx) return; ctx->passphrase_cb = cb; ctx->passphrase_cb_value = cb_value; } /* This function returns the callback function to be used to pass a passphrase to the crypto engine. */ void gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *r_cb, void **r_cb_value) { TRACE (DEBUG_CTX, "gpgme_get_passphrase_cb", NULL, "ctx=%lu passphrase_cb=%p/%p", CTXSERIAL (ctx), ctx->passphrase_cb, ctx->passphrase_cb_value); if (r_cb) *r_cb = ctx->passphrase_cb; if (r_cb_value) *r_cb_value = ctx->passphrase_cb_value; } /* This function sets a callback function to be used as a progress indicator. */ void gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb, void *cb_value) { TRACE (DEBUG_CTX, "gpgme_set_progress_cb", NULL, "ctx=%lu progress_cb=%p/%p", CTXSERIAL (ctx), cb, cb_value); if (!ctx) return; ctx->progress_cb = cb; ctx->progress_cb_value = cb_value; } /* This function returns the callback function to be used as a progress indicator. */ void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb, void **r_cb_value) { TRACE (DEBUG_CTX, "gpgme_get_progress_cb", NULL, "ctx=%lu progress_cb=%p/%p", CTXSERIAL (ctx), ctx->progress_cb, ctx->progress_cb_value); if (r_cb) *r_cb = ctx->progress_cb; if (r_cb_value) *r_cb_value = ctx->progress_cb_value; } /* This function sets a callback function to be used as a status message forwarder. */ void gpgme_set_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t cb, void *cb_value) { TRACE (DEBUG_CTX, "gpgme_set_status_cb", NULL, "ctx=%lu status_cb=%p/%p", CTXSERIAL (ctx), cb, cb_value); if (!ctx) return; ctx->status_cb = cb; ctx->status_cb_value = cb_value; } /* This function returns the callback function to be used as a status message forwarder. */ void gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *r_cb, void **r_cb_value) { TRACE (DEBUG_CTX, "gpgme_get_status_cb", NULL, "ctx=%lu status_cb=%p/%p", CTXSERIAL (ctx), ctx ? ctx->status_cb : NULL, ctx ? ctx->status_cb_value : NULL); if (r_cb) *r_cb = NULL; if (r_cb_value) *r_cb_value = NULL; if (!ctx || !ctx->status_cb) return; if (r_cb) *r_cb = ctx->status_cb; if (r_cb_value) *r_cb_value = ctx->status_cb_value; } /* Set the I/O callback functions for CTX to IO_CBS. */ void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs) { if (!ctx) return; if (io_cbs) { TRACE (DEBUG_CTX, "gpgme_set_io_cbs", NULL, "ctx=%lu io_cbs=%p (add=%p/%p, remove=%p, event=%p/%p", CTXSERIAL (ctx), io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove, io_cbs->event, io_cbs->event_priv); ctx->io_cbs = *io_cbs; } else { TRACE (DEBUG_CTX, "gpgme_set_io_cbs", NULL, "ctx=%lu io_cbs=%p (default)", CTXSERIAL (ctx), io_cbs); ctx->io_cbs.add = NULL; ctx->io_cbs.add_priv = NULL; ctx->io_cbs.remove = NULL; ctx->io_cbs.event = NULL; ctx->io_cbs.event_priv = NULL; } } /* This function provides access to the internal read function; it is normally not used. */ gpgme_ssize_t gpgme_io_read (int fd, void *buffer, size_t count) { int ret; TRACE_BEG (DEBUG_GLOBAL, "gpgme_io_read", NULL, "fd=%d buffer=%p count=%zu", fd, buffer, count); ret = _gpgme_io_read (fd, buffer, count); return TRACE_SYSRES (ret); } /* This function provides access to the internal write function. It is to be used by user callbacks to return data to gpgme. See gpgme_passphrase_cb_t and gpgme_edit_cb_t. */ gpgme_ssize_t gpgme_io_write (int fd, const void *buffer, size_t count) { int ret; TRACE_BEG (DEBUG_GLOBAL, "gpgme_io_write", NULL, "fd=%d buffer=%p count=%zu", fd, buffer, count); ret = _gpgme_io_write (fd, buffer, count); return TRACE_SYSRES (ret); } /* This function provides access to the internal write function. It is to be used by user callbacks to return data to gpgme. See gpgme_passphrase_cb_t and gpgme_edit_cb_t. Note that this is a variant of gpgme_io_write which guarantees that all COUNT bytes are written or an error is return. Returns: 0 on success or -1 on error and the sets errno. */ int gpgme_io_writen (int fd, const void *buffer_arg, size_t count) { const char *buffer = buffer_arg; int ret = 0; TRACE_BEG (DEBUG_GLOBAL, "gpgme_io_writen", NULL, "fd=%d buffer=%p count=%zu", fd, buffer, count); while (count) { ret = _gpgme_io_write (fd, buffer, count); if (ret < 0) break; buffer += ret; count -= ret; ret = 0; } return TRACE_SYSRES (ret); } /* This function returns the callback function for I/O. */ void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs) { TRACE (DEBUG_CTX, "gpgme_get_io_cbs", NULL, "ctx=%lu io_cbs=%p ctx->io_cbs.add=%p/%p .remove=%p, .event=%p/%p", CTXSERIAL (ctx), io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove, io_cbs->event, io_cbs->event_priv); *io_cbs = ctx->io_cbs; } /* This function sets the locale for the context CTX, or the default locale if CTX is a null pointer. */ gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value) { int failed = 0; char *new_lc_ctype = NULL; char *new_lc_messages = NULL; TRACE_BEG (DEBUG_CTX, "gpgme_set_locale", NULL, "ctx=%lu category=%i value=%s", CTXSERIAL (ctx), category, value ? value : "(null)"); #define PREPARE_ONE_LOCALE(lcat, ucat) \ if (!failed && value \ && (category == LC_ALL || category == LC_ ## ucat)) \ { \ new_lc_ ## lcat = strdup (value); \ if (!new_lc_ ## lcat) \ failed = 1; \ } #ifdef LC_CTYPE PREPARE_ONE_LOCALE (ctype, CTYPE); #endif #ifdef LC_MESSAGES PREPARE_ONE_LOCALE (messages, MESSAGES); #endif if (failed) { int saved_err = gpg_error_from_syserror (); if (new_lc_ctype) free (new_lc_ctype); if (new_lc_messages) free (new_lc_messages); return TRACE_ERR (saved_err); } #define SET_ONE_LOCALE(lcat, ucat) \ if (category == LC_ALL || category == LC_ ## ucat) \ { \ if (ctx) \ { \ if (ctx->lc_ ## lcat) \ free (ctx->lc_ ## lcat); \ ctx->lc_ ## lcat = new_lc_ ## lcat; \ } \ else \ { \ if (def_lc_ ## lcat) \ free (def_lc_ ## lcat); \ def_lc_ ## lcat = new_lc_ ## lcat; \ } \ } if (!ctx) - LOCK (def_lc_lock); + LOCK (context_list_lock); #ifdef LC_CTYPE SET_ONE_LOCALE (ctype, CTYPE); #endif #ifdef LC_MESSAGES SET_ONE_LOCALE (messages, MESSAGES); #endif if (!ctx) - UNLOCK (def_lc_lock); + UNLOCK (context_list_lock); return TRACE_ERR (0); } /* Get the information about the configured engines. A pointer to the first engine in the statically allocated linked list is returned. The returned data is valid until the next gpgme_ctx_set_engine_info. */ gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_ctx_get_engine_info", NULL, "ctx=%lu engine_info=%p", CTXSERIAL (ctx), ctx->engine_info); return ctx->engine_info; } /* Set the engine info for the context CTX, protocol PROTO, to the file name FILE_NAME and the home directory HOME_DIR. */ gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto, const char *file_name, const char *home_dir) { gpgme_error_t err; TRACE_BEG (DEBUG_CTX, "gpgme_ctx_set_engine_info", NULL, "ctx=%lu protocol=%i (%s), file_name=%s, home_dir=%s", CTXSERIAL (ctx), proto, gpgme_get_protocol_name (proto) ? gpgme_get_protocol_name (proto) : "unknown", file_name ? file_name : "(default)", home_dir ? home_dir : "(default)"); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); /* Shut down the engine when changing engine info. */ if (ctx->engine) { TRACE_LOG ("releasing ctx->engine=%p", ctx->engine); _gpgme_engine_release (ctx->engine); ctx->engine = NULL; } err = _gpgme_set_engine_info (ctx->engine_info, proto, file_name, home_dir); return TRACE_ERR (err); } /* Clear all notation data from the context. */ void _gpgme_sig_notation_clear (gpgme_ctx_t ctx) { gpgme_sig_notation_t notation; if (!ctx) return; notation = ctx->sig_notations; while (notation) { gpgme_sig_notation_t next_notation = notation->next; _gpgme_sig_notation_free (notation); notation = next_notation; } ctx->sig_notations = NULL; } void gpgme_sig_notation_clear (gpgme_ctx_t ctx) { TRACE (DEBUG_CTX, "gpgme_sig_notation_clear", NULL, "ctx=%lu", CTXSERIAL (ctx)); if (!ctx) return; _gpgme_sig_notation_clear (ctx); } /* Add the human-readable notation data with name NAME and value VALUE to the context CTX, using the flags FLAGS. If NAME is NULL, then VALUE should be a policy URL. The flag GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation data, and false for policy URLs. */ gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name, const char *value, gpgme_sig_notation_flags_t flags) { gpgme_error_t err; gpgme_sig_notation_t notation; gpgme_sig_notation_t *lastp; TRACE_BEG (DEBUG_CTX, "gpgme_sig_notation_add", NULL, "ctx=%lu name=%s value=%s flags=0x%x", CTXSERIAL (ctx), name ? name : "(null)", value ? value : "(null)", flags); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (name) flags |= GPGME_SIG_NOTATION_HUMAN_READABLE; else flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE; err = _gpgme_sig_notation_create (¬ation, name, name ? strlen (name) : 0, value, value ? strlen (value) : 0, flags); if (err) return TRACE_ERR (err); lastp = &ctx->sig_notations; while (*lastp) lastp = &(*lastp)->next; *lastp = notation; return TRACE_ERR (0); } /* Get the sig notations for this context. */ gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx) { if (!ctx) { TRACE (DEBUG_CTX, "gpgme_sig_notation_get", NULL, "ctx=%lu", CTXSERIAL (ctx)); return NULL; } TRACE (DEBUG_CTX, "gpgme_sig_notation_get", NULL, "ctx=%lu sig_notations=%p", CTXSERIAL (ctx), ctx->sig_notations); return ctx->sig_notations; } /* Return a public key algorithm string made of the algorithm and size or the curve name. May return NULL on error. Caller must free the result using gpgme_free. */ char * gpgme_pubkey_algo_string (gpgme_subkey_t subkey) { const char *prefix = NULL; char *result; if (!subkey) { gpg_err_set_errno (EINVAL); return NULL; } switch (subkey->pubkey_algo) { case GPGME_PK_RSA: case GPGME_PK_RSA_E: case GPGME_PK_RSA_S: prefix = "rsa"; break; case GPGME_PK_ELG_E: prefix = "elg"; break; case GPGME_PK_DSA: prefix = "dsa"; break; case GPGME_PK_ELG: prefix = "xxx"; break; case GPGME_PK_ECC: case GPGME_PK_ECDH: case GPGME_PK_ECDSA: case GPGME_PK_EDDSA: prefix = ""; break; } if (prefix && *prefix) { char buffer[40]; snprintf (buffer, sizeof buffer, "%s%u", prefix, subkey->length); result = strdup (buffer); } else if (prefix && subkey->curve && *subkey->curve) result = strdup (subkey->curve); else if (prefix) result = strdup ("E_error"); else result = strdup ("unknown"); return result; } const char * gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo) { switch (algo) { case GPGME_PK_RSA: return "RSA"; case GPGME_PK_RSA_E: return "RSA-E"; case GPGME_PK_RSA_S: return "RSA-S"; case GPGME_PK_ELG_E: return "ELG-E"; case GPGME_PK_DSA: return "DSA"; case GPGME_PK_ECC: return "ECC"; case GPGME_PK_ELG: return "ELG"; case GPGME_PK_ECDSA: return "ECDSA"; case GPGME_PK_ECDH: return "ECDH"; case GPGME_PK_EDDSA: return "EdDSA"; default: return NULL; } } const char * gpgme_hash_algo_name (gpgme_hash_algo_t algo) { switch (algo) { case GPGME_MD_MD5: return "MD5"; case GPGME_MD_SHA1: return "SHA1"; case GPGME_MD_RMD160: return "RIPEMD160"; case GPGME_MD_MD2: return "MD2"; case GPGME_MD_TIGER: return "TIGER192"; case GPGME_MD_HAVAL: return "HAVAL"; case GPGME_MD_SHA256: return "SHA256"; case GPGME_MD_SHA384: return "SHA384"; case GPGME_MD_SHA512: return "SHA512"; case GPGME_MD_SHA224: return "SHA224"; case GPGME_MD_MD4: return "MD4"; case GPGME_MD_CRC32: return "CRC32"; case GPGME_MD_CRC32_RFC1510: return "CRC32RFC1510"; case GPGME_MD_CRC24_RFC2440: return "CRC24RFC2440"; default: return NULL; } } diff --git a/src/ops.h b/src/ops.h index 3b9728dd..013b2cd2 100644 --- a/src/ops.h +++ b/src/ops.h @@ -1,195 +1,192 @@ /* ops.h - Internal operation support. Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004, 2005 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OPS_H #define OPS_H #include "gpgme.h" #include "context.h" -/* From gpgme.c. */ -gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err, - gpg_error_t op_err); /* Clear all notation data from the context. */ void _gpgme_sig_notation_clear (gpgme_ctx_t ctx); void _gpgme_release_result (gpgme_ctx_t ctx); /* From wait.c. */ gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx); gpgme_error_t _gpgme_wait_one_ext (gpgme_ctx_t ctx, gpgme_error_t *op_err); gpgme_error_t _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond, gpgme_error_t *op_err); /* From data.c. */ gpgme_error_t _gpgme_data_inbound_handler (void *opaque, int fd); gpgme_error_t _gpgme_data_outbound_handler (void *opaque, int fd); /* From op-support.c. */ /* Find or create the op data object of type TYPE. */ gpgme_error_t _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook, int size, void (*cleanup) (void *)); /* Prepare a new operation on CTX. */ gpgme_error_t _gpgme_op_reset (gpgme_ctx_t ctx, int synchronous); /* Parse the KEY_CONSIDERED status line. */ gpgme_error_t _gpgme_parse_key_considered (const char *args, char **r_fpr, unsigned int *r_flags); /* Parse the INV_RECP status line in ARGS and return the result in KEY. */ gpgme_error_t _gpgme_parse_inv_recp (char *args, int for_signing, const char *kc_fpr, unsigned int kc_flags, gpgme_invalid_key_t *key); /* Parse the PLAINTEXT status line in ARGS and return the result in FILENAMEP and R_MIME. */ gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep,int *r_mime); /* Parse a FAILURE status line and return the error code. ARGS is modified to contain the location part. */ gpgme_error_t _gpgme_parse_failure (char *args); /* From verify.c. */ gpgme_error_t _gpgme_op_verify_init_result (gpgme_ctx_t ctx); gpgme_error_t _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args); /* From decrypt.c. */ gpgme_error_t _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx, gpgme_data_t plaintext); gpgme_error_t _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args); gpgme_error_t _gpgme_decrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_decrypt_flags_t flags, gpgme_data_t cipher, gpgme_data_t plain); /* From signers.c. */ void _gpgme_signers_clear (gpgme_ctx_t ctx); /* From sign.c. */ /* Create an initial op data object for signing. Needs to be called once before calling _gpgme_sign_status_handler. */ gpgme_error_t _gpgme_op_sign_init_result (gpgme_ctx_t ctx); /* Process a status line for signing operations. */ gpgme_error_t _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args); /* From encrypt.c. */ /* Create an initial op data object for encrypt. Needs to be called once before calling _gpgme_encrypt_status_handler. */ gpgme_error_t _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx); /* Process a status line for encryption operations. */ gpgme_error_t _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args); /* From passphrase.c. */ gpgme_error_t _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code, char *args); gpgme_error_t _gpgme_passphrase_command_handler (void *opaque, gpgme_status_code_t code, const char *key, int fd, int *processed); /* From progress.c. */ gpgme_error_t _gpgme_progress_status_handler (void *priv, gpgme_status_code_t code, char *args); /* From key.c. */ gpgme_error_t _gpgme_key_new (gpgme_key_t *r_key); gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key, gpgme_subkey_t *r_subkey); gpgme_error_t _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert); gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src); /* From keylist.c. */ void _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data); /* From trust-item.c. */ /* Create a new trust item. */ gpgme_error_t _gpgme_trust_item_new (gpgme_trust_item_t *r_item); /* From trustlist.c. */ void _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type, void *type_data); /* From version.c. */ /* Return true if MY_VERSION is at least REQ_VERSION, and false otherwise. */ int _gpgme_compare_versions (const char *my_version, const char *req_version); char *_gpgme_get_program_version (const char *const path); /* From sig-notation.c. */ /* Create a new, empty signature notation data object. */ gpgme_error_t _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp, const char *name, int name_len, const char *value, int value_len, gpgme_sig_notation_flags_t flags); /* Free the signature notation object and all associated resources. The object must already be removed from any linked list as the next pointer is ignored. */ void _gpgme_sig_notation_free (gpgme_sig_notation_t notation); /* Parse a notation or policy URL subpacket. If the packet type is not known, return no error but NULL in NOTATION. */ gpgme_error_t _gpgme_parse_notation (gpgme_sig_notation_t *notationp, int type, int pkflags, int len, char *data); #endif /* OPS_H */