diff options
author | JinWang An <jinwang.an@samsung.com> | 2021-12-01 16:54:36 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2021-12-01 16:54:36 +0900 |
commit | 214479142a766516e8770c3e1a3b0b0cc37c239e (patch) | |
tree | 43ff2d595b2e19d2f3e35ce6cf74a9e4a63ab3e7 /src | |
parent | 3a4efa5aa27f73c93a1b020b8b30f07f0b4e46c7 (diff) | |
download | gpgme-214479142a766516e8770c3e1a3b0b0cc37c239e.tar.gz gpgme-214479142a766516e8770c3e1a3b0b0cc37c239e.tar.bz2 gpgme-214479142a766516e8770c3e1a3b0b0cc37c239e.zip |
Imported Upstream version 1.9.0upstream/1.9.0
Diffstat (limited to 'src')
40 files changed, 1178 insertions, 903 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 3f0da74..5f153a8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -107,8 +107,8 @@ subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/mkinstalldirs \ $(srcdir)/versioninfo.rc.in $(srcdir)/gpgme.h.in \ - $(srcdir)/gpgme-config.in stpcpy.c funopen.c ttyname_r.c \ - vasprintf.c setenv.c $(top_srcdir)/build-aux/depcomp + $(srcdir)/gpgme-config.in stpcpy.c ttyname_r.c setenv.c \ + $(top_srcdir)/build-aux/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/ax_pkg_swig.m4 \ @@ -119,8 +119,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ - $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/python.m4 $(top_srcdir)/m4/qt.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs @@ -818,11 +818,9 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/funopen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/setenv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stpcpy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ttyname_r.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/vasprintf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assuan-support.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ath.Plo@am__quote@ diff --git a/src/context.h b/src/context.h index 1a8698c..d0542d9 100644 --- a/src/context.h +++ b/src/context.h @@ -114,10 +114,14 @@ struct gpgme_context /* 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; + /* Flags for keylist mode. */ gpgme_keylist_mode_t keylist_mode; - /* The current pinnetry mode. */ + /* The current pinentry mode. */ gpgme_pinentry_mode_t pinentry_mode; /* Number of certs to be included. */ diff --git a/src/conversion.c b/src/conversion.c index 6dfabe7..92dd214 100644 --- a/src/conversion.c +++ b/src/conversion.c @@ -536,6 +536,25 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp) } +/* This function is similar to _gpgme_parse_timestamp but returns an + * unsigned long and 0 on error. */ +unsigned long +_gpgme_parse_timestamp_ul (const char *timestamp) +{ + time_t tim; + char *tail; + + if (!*timestamp) + return 0; /* Shortcut empty strings. */ + + tim = _gpgme_parse_timestamp (timestamp, &tail); + if (tim == -1 || timestamp == tail || (*tail && *tail != ' ')) + tim = 0; /* No time given or invalid engine. */ + + return (unsigned long)tim; +} + + /* The GPG backend uses OpenPGP algorithm numbers which we need to map to our algorithm numbers. This function MUST not change ERRNO. */ int diff --git a/src/data-compat.c b/src/data-compat.c index 5c7d543..87eaeef 100644 --- a/src/data-compat.c +++ b/src/data-compat.c @@ -239,16 +239,3 @@ gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, (*r_dh)->data.old_user.handle = read_cb_value; return TRACE_ERR (0); } - - -gpgme_error_t -gpgme_data_rewind (gpgme_data_t dh) -{ - gpgme_error_t err; - TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh); - - err = ((gpgme_data_seek (dh, 0, SEEK_SET) == -1) - ? gpg_error_from_syserror () : 0); - - return TRACE_ERR (err); -} @@ -158,6 +158,20 @@ gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence) } +/* Convenience function to do a gpgme_data_seek (dh, 0, SEEK_SET). */ +gpgme_error_t +gpgme_data_rewind (gpgme_data_t dh) +{ + gpgme_error_t err; + TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh); + + err = ((gpgme_data_seek (dh, 0, SEEK_SET) == -1) + ? gpg_error_from_syserror () : 0); + + return TRACE_ERR (err); +} + + /* Release the data object with the handle DH. */ void gpgme_data_release (gpgme_data_t dh) diff --git a/src/debug.c b/src/debug.c index 1dd3723..e9bfc40 100644 --- a/src/debug.c +++ b/src/debug.c @@ -313,7 +313,7 @@ _gpgme_debug_begin (void **line, int level, const char *format, ...) } va_start (arg_ptr, format); - res = vasprintf ((char **) line, format, arg_ptr); + res = gpgrt_vasprintf ((char **) line, format, arg_ptr); va_end (arg_ptr); if (res < 0) *line = NULL; @@ -333,16 +333,16 @@ _gpgme_debug_add (void **line, const char *format, ...) return; va_start (arg_ptr, format); - res = vasprintf (&toadd, format, arg_ptr); + res = gpgrt_vasprintf (&toadd, format, arg_ptr); va_end (arg_ptr); if (res < 0) { - free (*line); + gpgrt_free (*line); *line = NULL; } - res = asprintf (&result, "%s%s", *(char **) line, toadd); - free (toadd); - free (*line); + res = gpgrt_asprintf (&result, "%s%s", *(char **) line, toadd); + gpgrt_free (toadd); + gpgrt_free (*line); if (res < 0) *line = NULL; else @@ -361,7 +361,7 @@ _gpgme_debug_end (void **line) /* The smallest possible level is 1, so force logging here by using that. */ _gpgme_debug (1, "%s", *line); - free (*line); + gpgrt_free (*line); *line = NULL; } diff --git a/src/decrypt-verify.c b/src/decrypt-verify.c index e0aa8ea..66cfe94 100644 --- a/src/decrypt-verify.c +++ b/src/decrypt-verify.c @@ -23,6 +23,8 @@ #include <config.h> #endif +#include <assert.h> + #include "debug.h" #include "gpgme.h" #include "ops.h" @@ -45,10 +47,13 @@ decrypt_verify_status_handler (void *priv, gpgme_status_code_t code, static gpgme_error_t decrypt_verify_start (gpgme_ctx_t ctx, int synchronous, + gpgme_decrypt_flags_t flags, gpgme_data_t cipher, gpgme_data_t plain) { gpgme_error_t err; + assert ((flags & GPGME_DECRYPT_VERIFY)); + err = _gpgme_op_reset (ctx, synchronous); if (err) return err; @@ -77,9 +82,11 @@ decrypt_verify_start (gpgme_ctx_t ctx, int synchronous, _gpgme_engine_set_status_handler (ctx->engine, decrypt_verify_status_handler, ctx); - return _gpgme_engine_op_decrypt_verify (ctx->engine, cipher, plain, - ctx->export_session_keys, - ctx->override_session_key); + return _gpgme_engine_op_decrypt (ctx->engine, + flags, + cipher, plain, + ctx->export_session_keys, + ctx->override_session_key); } @@ -97,7 +104,7 @@ gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_data_t cipher, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = decrypt_verify_start (ctx, 0, cipher, plain); + err = decrypt_verify_start (ctx, 0, GPGME_DECRYPT_VERIFY, cipher, plain); return TRACE_ERR (err); } @@ -116,7 +123,57 @@ gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = decrypt_verify_start (ctx, 1, cipher, plain); + err = decrypt_verify_start (ctx, 1, GPGME_DECRYPT_VERIFY, cipher, plain); + if (!err) + err = _gpgme_wait_one (ctx); + return TRACE_ERR (err); +} + + +/* Decrypt ciphertext CIPHER within CTX and store the resulting + plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_decrypt_ext_start (gpgme_ctx_t ctx, + gpgme_decrypt_flags_t flags, + gpgme_data_t cipher, + gpgme_data_t plain) +{ + gpgme_error_t err; + + TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_ext_start", ctx, + "cipher=%p, plain=%p", cipher, plain); + + if (!ctx) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if ((flags & GPGME_DECRYPT_VERIFY)) + err = decrypt_verify_start (ctx, 0, flags, cipher, plain); + else + err = _gpgme_decrypt_start (ctx, 0, flags, cipher, plain); + return TRACE_ERR (err); +} + + +/* Decrypt ciphertext CIPHER within CTX and store the resulting + plaintext in PLAIN. */ +gpgme_error_t +gpgme_op_decrypt_ext (gpgme_ctx_t ctx, + gpgme_decrypt_flags_t flags, + gpgme_data_t cipher, + gpgme_data_t plain) +{ + gpgme_error_t err; + + TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_ext", ctx, + "cipher=%p, plain=%p", cipher, plain); + + if (!ctx) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + if ((flags & GPGME_DECRYPT_VERIFY)) + err = decrypt_verify_start (ctx, 1, flags, cipher, plain); + else + err = _gpgme_decrypt_start (ctx, 1, flags, cipher, plain); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); diff --git a/src/decrypt.c b/src/decrypt.c index 43717c0..f30f80f 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <assert.h> #include "debug.h" #include "gpgme.h" @@ -358,12 +359,15 @@ _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx) } -static gpgme_error_t -decrypt_start (gpgme_ctx_t ctx, int synchronous, - gpgme_data_t cipher, gpgme_data_t plain) +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) { gpgme_error_t err; + assert (!(flags & GPGME_DECRYPT_VERIFY)); + err = _gpgme_op_reset (ctx, synchronous); if (err) return err; @@ -390,7 +394,9 @@ decrypt_start (gpgme_ctx_t ctx, int synchronous, _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx); - return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain, + return _gpgme_engine_op_decrypt (ctx->engine, + flags, + cipher, plain, ctx->export_session_keys, ctx->override_session_key); } @@ -408,7 +414,7 @@ gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = decrypt_start (ctx, 0, cipher, plain); + err = _gpgme_decrypt_start (ctx, 0, 0, cipher, plain); return TRACE_ERR (err); } @@ -426,7 +432,7 @@ gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain) if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); - err = decrypt_start (ctx, 1, cipher, plain); + err = _gpgme_decrypt_start (ctx, 1, 0, cipher, plain); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); diff --git a/src/dirinfo.c b/src/dirinfo.c index a0cbc03..7374412 100644 --- a/src/dirinfo.c +++ b/src/dirinfo.c @@ -51,6 +51,7 @@ enum WANT_GPG_NAME, WANT_GPGSM_NAME, WANT_G13_NAME, + WANT_GPG_WKS_CLIENT_NAME, WANT_GPG_ONE_MODE }; @@ -73,6 +74,7 @@ static struct { char *gpg_name; char *gpgsm_name; char *g13_name; + char *gpg_wks_client_name; int gpg_one_mode; /* System is in gpg1 mode. */ } dirinfo; @@ -333,6 +335,14 @@ get_gpgconf_item (int what) case WANT_G13_NAME: result = dirinfo.g13_name; break; case WANT_UISRV_SOCKET: result = dirinfo.uisrv_socket; break; case WANT_GPG_ONE_MODE: result = dirinfo.gpg_one_mode? "1":NULL; break; + case WANT_GPG_WKS_CLIENT_NAME: + if (!dirinfo.gpg_wks_client_name && dirinfo.libexecdir) + dirinfo.gpg_wks_client_name = _gpgme_strconcat (dirinfo.libexecdir, + "/", + "gpg-wks-client", + NULL); + result = dirinfo.gpg_wks_client_name; + break; } UNLOCK (dirinfo_lock); return result; @@ -438,6 +448,8 @@ gpgme_get_dirinfo (const char *what) return get_gpgconf_item (WANT_GPGSM_NAME); else if (!strcmp (what, "g13-name")) return get_gpgconf_item (WANT_G13_NAME); + else if (!strcmp (what, "gpg-wks-client-name")) + return get_gpgconf_item (WANT_GPG_WKS_CLIENT_NAME); else if (!strcmp (what, "agent-ssh-socket")) return get_gpgconf_item (WANT_AGENT_SSH_SOCKET); else if (!strcmp (what, "dirmngr-socket")) diff --git a/src/engine-assuan.c b/src/engine-assuan.c index 3e3b89f..68bdaa6 100644 --- a/src/engine-assuan.c +++ b/src/engine-assuan.c @@ -265,7 +265,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_display) { - if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0) + if (gpgrt_asprintf (&optstr, "OPTION display=%s", dft_display) < 0) { err = gpg_error_from_syserror (); free (dft_display); @@ -275,7 +275,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -304,14 +304,14 @@ llass_new (void **engine, const char *file_name, const char *home_dir, ways, e.g., when /dev/pts is not accessible under chroot. */ if (!rc) { - if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) { err = gpg_error_from_syserror (); goto leave; } err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; @@ -320,7 +320,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_ttytype) { - if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype)< 0) { err = gpg_error_from_syserror (); free (dft_ttytype); @@ -330,7 +330,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -408,13 +408,13 @@ llass_set_locale (void *engine, int category, const char *value) if (!value) return 0; - if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) + if (gpgrt_asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) err = gpg_error_from_syserror (); else { err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); } return err; } @@ -776,7 +776,6 @@ struct engine_ops _gpgme_engine_ops_assuan = llass_set_locale, NULL, /* set_protocol */ NULL, /* decrypt */ - NULL, /* decrypt_verify */ NULL, /* delete */ NULL, /* edit */ NULL, /* encrypt */ @@ -787,6 +786,7 @@ struct engine_ops _gpgme_engine_ops_assuan = NULL, /* import */ NULL, /* keylist */ NULL, /* keylist_ext */ + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ NULL, /* sign */ diff --git a/src/engine-backend.h b/src/engine-backend.h index a8457af..53af662 100644 --- a/src/engine-backend.h +++ b/src/engine-backend.h @@ -61,12 +61,11 @@ struct engine_ops void *fnc_value); gpgme_error_t (*set_locale) (void *engine, int category, const char *value); gpgme_error_t (*set_protocol) (void *engine, gpgme_protocol_t protocol); - gpgme_error_t (*decrypt) (void *engine, gpgme_data_t ciph, + gpgme_error_t (*decrypt) (void *engine, + gpgme_decrypt_flags_t flags, + gpgme_data_t ciph, gpgme_data_t plain, int export_session_key, const char *override_session_key); - gpgme_error_t (*decrypt_verify) (void *engine, gpgme_data_t ciph, - gpgme_data_t plain, int export_session_key, - const char *override_session_key); gpgme_error_t (*delete) (void *engine, gpgme_key_t key, int allow_secret); gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key, gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */); @@ -100,6 +99,7 @@ struct engine_ops int secret_only, int reserved, gpgme_keylist_mode_t mode, int engine_flags); + gpgme_error_t (*keylist_data) (void *engine, gpgme_data_t data); gpgme_error_t (*keysign) (void *engine, gpgme_key_t key, const char *userid, unsigned long expires, unsigned int flags, diff --git a/src/engine-g13.c b/src/engine-g13.c index 972c3a8..02951e8 100644 --- a/src/engine-g13.c +++ b/src/engine-g13.c @@ -270,7 +270,7 @@ g13_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_display) { - if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0) + if (gpgrt_asprintf (&optstr, "OPTION display=%s", dft_display) < 0) { free (dft_display); err = gpg_error_from_syserror (); @@ -280,7 +280,7 @@ g13_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -304,14 +304,14 @@ g13_new (void **engine, const char *file_name, const char *home_dir, ways, e.g., when /dev/pts is not accessible under chroot. */ if (!rc) { - if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) { err = gpg_error_from_syserror (); goto leave; } err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; @@ -320,7 +320,7 @@ g13_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_ttytype) { - if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype)< 0) { free (dft_ttytype); err = gpg_error_from_syserror (); @@ -330,7 +330,7 @@ g13_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -400,13 +400,13 @@ g13_set_locale (void *engine, int category, const char *value) if (!value) return 0; - if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) + if (gpgrt_asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) err = gpg_error_from_syserror (); else { err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); } return err; @@ -791,7 +791,6 @@ struct engine_ops _gpgme_engine_ops_g13 = g13_set_locale, NULL, /* set_protocol */ NULL, /* decrypt */ - NULL, /* decrypt_verify */ NULL, /* delete */ NULL, /* edit */ NULL, /* encrypt */ @@ -802,6 +801,7 @@ struct engine_ops _gpgme_engine_ops_g13 = NULL, /* import */ NULL, /* keylist */ NULL, /* keylist_ext */ + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ NULL, /* sign */ diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 3ddaa07..0c3a63e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -74,6 +74,10 @@ struct fd_data_map_s }; +/* NB.: R_LINE is allocated an gpgrt function and thus gpgrt_free + * shall be used to release it. This takes care of custom memory + * allocators and avoids problems on Windows with different runtimes + * used for libgpg-error/gpgrt and gpgme. */ typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline); struct engine_gpg @@ -1346,7 +1350,7 @@ read_colon_line (engine_gpg_t gpg) } while (linep && *linep); - free (line); + gpgrt_free (line); } else gpg->colon.fnc (gpg->colon.fnc_value, buffer); @@ -1555,7 +1559,9 @@ add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data) static gpgme_error_t -gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain, +gpg_decrypt (void *engine, + gpgme_decrypt_flags_t flags, + gpgme_data_t ciph, gpgme_data_t plain, int export_session_key, const char *override_session_key) { engine_gpg_t gpg = engine; @@ -1563,6 +1569,14 @@ gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain, err = add_arg (gpg, "--decrypt"); + if (!err && (flags & GPGME_DECRYPT_UNWRAP)) + { + if (!have_gpg_version (gpg, "2.1.12")) + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + else + err = add_arg (gpg, "--unwrap"); + } + if (!err && export_session_key) err = add_arg (gpg, "--show-session-key"); @@ -1853,9 +1867,23 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!err && use_armor) err = add_arg (gpg, "--armor"); + if (!err && (flags & GPGME_ENCRYPT_WRAP)) + { + /* gpg is current not abale to detect already compressed + * packets. Thus when using + * gpg --unwrap -d | gpg --no-literal -e + * the encryption would add an additional compression layer. + * We better suppress that. */ + flags |= GPGME_ENCRYPT_NO_COMPRESS; + err = add_arg (gpg, "--no-literal"); + } + if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) err = add_arg (gpg, "--compress-algo=none"); + if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) + err = add_arg (gpg, "--throw-keyids"); + if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); @@ -1925,6 +1953,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) err = add_arg (gpg, "--compress-algo=none"); + if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) + err = add_arg (gpg, "--throw-keyids"); + if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); @@ -2072,7 +2103,8 @@ gpg_add_algo_usage_expire (engine_gpg_t gpg, /* This condition is only required to allow the use of gpg < 2.1.16 */ if (algo || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR - | GPGME_CREATE_CERT | GPGME_CREATE_AUTH)) + | GPGME_CREATE_CERT | GPGME_CREATE_AUTH + | GPGME_CREATE_NOEXPIRE)) || expires) { err = add_arg (gpg, algo? algo : "default"); @@ -2086,11 +2118,18 @@ gpg_add_algo_usage_expire (engine_gpg_t gpg, (flags & GPGME_CREATE_AUTH)? " auth":""); err = add_arg (gpg, *tmpbuf? tmpbuf : "default"); } - if (!err && expires) + if (!err) { - char tmpbuf[8+20]; - snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires); - err = add_arg (gpg, tmpbuf); + if ((flags & GPGME_CREATE_NOEXPIRE)) + err = add_arg (gpg, "never"); + else if (expires == 0) + err = add_arg (gpg, "-"); + else + { + char tmpbuf[8+20]; + snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires); + err = add_arg (gpg, tmpbuf); + } } } else @@ -2136,6 +2175,8 @@ gpg_createkey (engine_gpg_t gpg, err = add_arg (gpg, "--passphrase"); if (!err) err = add_arg (gpg, ""); + if (!err) + err = add_arg (gpg, "--batch"); } if (!err && (flags & GPGME_CREATE_FORCE)) err = add_arg (gpg, "--yes"); @@ -2174,6 +2215,8 @@ gpg_addkey (engine_gpg_t gpg, err = add_arg (gpg, "--passphrase"); if (!err) err = add_arg (gpg, ""); + if (!err) + err = add_arg (gpg, "--batch"); } if (!err) err = add_arg (gpg, "--"); @@ -2200,7 +2243,14 @@ gpg_adduid (engine_gpg_t gpg, if (!key || !key->fpr || !userid) return gpg_error (GPG_ERR_INV_ARG); - if ((extraflags & GENKEY_EXTRAFLAG_REVOKE)) + if ((extraflags & GENKEY_EXTRAFLAG_SETPRIMARY)) + { + if (!have_gpg_version (gpg, "2.1.20")) + err = gpg_error (GPG_ERR_NOT_SUPPORTED); + else + err = add_arg (gpg, "--quick-set-primary-uid"); + } + else if ((extraflags & GENKEY_EXTRAFLAG_REVOKE)) err = add_arg (gpg, "--quick-revuid"); else err = add_arg (gpg, "--quick-adduid"); @@ -2240,7 +2290,7 @@ gpg_genkey (void *engine, * USERID && !KEY - Create a new keyblock. * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14) * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14). - * + * or set a flag on a user id. */ if (help_data) { @@ -2509,7 +2559,7 @@ gpg_keylist_preprocess (char *line, char **r_line) n = strlen (field[1]); if (n > 16) { - if (asprintf (r_line, + if (gpgrt_asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::\n" "fpr:::::::::%s:", field[6], field[3], field[2], field[1] + n - 16, @@ -2518,7 +2568,7 @@ gpg_keylist_preprocess (char *line, char **r_line) } else { - if (asprintf (r_line, + if (gpgrt_asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::", field[6], field[3], field[2], field[1], field[4], field[5]) < 0) @@ -2576,7 +2626,7 @@ gpg_keylist_preprocess (char *line, char **r_line) } *dst = '\0'; - if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:", + if (gpgrt_asprintf (r_line, "uid:o%s::::%s:%s:::%s:", field[4], field[2], field[3], uid) < 0) return gpg_error_from_syserror (); } @@ -2715,6 +2765,38 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only, static gpgme_error_t +gpg_keylist_data (void *engine, gpgme_data_t data) +{ + engine_gpg_t gpg = engine; + gpgme_error_t err; + + if (!have_gpg_version (gpg, "2.1.14")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + err = add_arg (gpg, "--with-colons"); + if (!err) + err = add_arg (gpg, "--with-fingerprint"); + if (!err) + err = add_arg (gpg, "--import-options"); + if (!err) + err = add_arg (gpg, "import-show"); + if (!err) + err = add_arg (gpg, "--dry-run"); + if (!err) + err = add_arg (gpg, "--import"); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, data, -1, 0); + + if (!err) + err = start (gpg); + + return err; +} + + +static gpgme_error_t gpg_keysign (void *engine, gpgme_key_t key, const char *userid, unsigned long expire, unsigned int flags, gpgme_ctx_t ctx) @@ -2986,7 +3068,6 @@ struct engine_ops _gpgme_engine_ops_gpg = gpg_set_locale, NULL, /* set_protocol */ gpg_decrypt, - gpg_decrypt, /* decrypt_verify */ gpg_delete, gpg_edit, gpg_encrypt, @@ -2997,6 +3078,7 @@ struct engine_ops _gpgme_engine_ops_gpg = gpg_import, gpg_keylist, gpg_keylist_ext, + gpg_keylist_data, gpg_keysign, gpg_tofu_policy, /* tofu_policy */ gpg_sign, diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index 2ea8673..6f7c8ac 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -708,10 +708,13 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) #define BUFLEN 1024 char buf[BUFLEN]; int buflen = 0; - char *argv[6]; + char *argv[7]; int argc = 0; - int rp[2]; - struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} }; + int rp[2] = { -1, -1 }; + int errp[2] = { -1, -1 }; + struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, + {-1, 2 /* STDERR_FILENO */, -1}, + {-1, -1} }; int status; int nwrite; @@ -724,25 +727,38 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) argv[argc++] = gpgconf->home_dir; } + argv[argc++] = (char*)"--runtime"; argv[argc++] = (char*)arg1; argv[argc++] = arg2; argv[argc] = NULL; assert (argc < DIM (argv)); if (_gpgme_io_pipe (rp, 0) < 0) - return gpg_error_from_syserror (); + { + err = gpg_error_from_syserror (); + goto leave; + } + + if (_gpgme_io_pipe (errp, 1) < 0) + { + err = gpg_error_from_syserror (); + goto leave; + } cfd[0].fd = rp[0]; + cfd[1].fd = errp[1]; status = _gpgme_io_spawn (gpgconf->file_name, argv, IOSPAWN_FLAG_DETACHED, cfd, NULL, NULL, NULL); if (status < 0) { - _gpgme_io_close (rp[0]); - _gpgme_io_close (rp[1]); - return gpg_error_from_syserror (); + err = gpg_error_from_syserror (); + goto leave; } + rp[0] = -1; + errp[1] = -1; + for (;;) { if (buflen == 0) @@ -756,14 +772,29 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) if (buflen < 0) { err = gpg_error_from_syserror (); - _gpgme_io_close (rp[1]); - return err; + goto leave; } else if (buflen == 0) { /* All is written. */ _gpgme_io_close (rp[1]); - return 0; + rp[1] = -1; + + for (;;) + { + do + { + buflen = _gpgme_io_read (errp[0], buf, BUFLEN); + } + while (buflen < 0 && errno == EAGAIN); + + if (buflen == 0) + { + err = 0; + goto leave; + } + /* XXX: Do something useful with BUF. */ + } } } @@ -781,12 +812,24 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) } else if (nwrite < 0) { - _gpgme_io_close (rp[1]); - return gpg_error_from_syserror (); + err = gpg_error_from_syserror (); + goto leave; } } - return 0; + assert (! "reached"); + + leave: + if (rp[0] != -1) + _gpgme_io_close (rp[0]); + if (rp[1] != -1) + _gpgme_io_close (rp[1]); + if (errp[0] != -1) + _gpgme_io_close (errp[0]); + if (errp[1] != -1) + _gpgme_io_close (errp[1]); + + return err; } @@ -1190,7 +1233,6 @@ struct engine_ops _gpgme_engine_ops_gpgconf = NULL, /* set_locale */ NULL, /* set_protocol */ NULL, /* decrypt */ - NULL, /* decrypt_verify */ NULL, /* delete */ NULL, /* edit */ NULL, /* encrypt */ @@ -1201,6 +1243,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf = NULL, /* import */ NULL, /* keylist */ NULL, /* keylist_ext */ + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ NULL, /* sign */ diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index d1be049..c3d5427 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -396,7 +396,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_display) { - if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0) + if (gpgrt_asprintf (&optstr, "OPTION display=%s", dft_display) < 0) { free (dft_display); err = gpg_error_from_syserror (); @@ -406,7 +406,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -430,14 +430,14 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir, ways, e.g., when /dev/pts is not accessible under chroot. */ if (!rc) { - if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) { err = gpg_error_from_syserror (); goto leave; } err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; @@ -446,7 +446,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_ttytype) { - if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype)< 0) { free (dft_ttytype); err = gpg_error_from_syserror (); @@ -456,7 +456,7 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -561,13 +561,13 @@ gpgsm_set_locale (void *engine, int category, const char *value) if (!value) return 0; - if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) + if (gpgrt_asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) err = gpg_error_from_syserror (); else { err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); } return err; @@ -593,7 +593,7 @@ gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd, { err = assuan_read_line (ctx, &line, &linelen); if (err) - return err; + break; if (*line == '#' || !linelen) continue; @@ -601,7 +601,7 @@ gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd, if (linelen >= 2 && line[0] == 'O' && line[1] == 'K' && (line[2] == '\0' || line[2] == ' ')) - return cb_err; + break; else if (linelen >= 4 && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' && line[3] == ' ') @@ -610,6 +610,7 @@ gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd, more related to gpgme and thus probably more important than the error returned by the engine. */ err = cb_err? cb_err : atoi (&line[4]); + cb_err = 0; } else if (linelen >= 2 && line[0] == 'S' && line[1] == ' ') @@ -646,10 +647,16 @@ gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd, to stop. As with ERR we prefer a status callback generated error code, though. */ err = cb_err ? cb_err : gpg_error (GPG_ERR_GENERAL); + cb_err = 0; } } while (!err); + /* We only want the first error from the status handler, thus we + * take the one saved in CB_ERR. */ + if (!err && cb_err) + err = cb_err; + return err; } @@ -1120,12 +1127,16 @@ gpgsm_reset (void *engine) static gpgme_error_t -gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain, +gpgsm_decrypt (void *engine, + gpgme_decrypt_flags_t flags, + gpgme_data_t ciph, gpgme_data_t plain, int export_session_key, const char *override_session_key) { engine_gpgsm_t gpgsm = engine; gpgme_error_t err; + (void)flags; + /* gpgsm is not capable of exporting session keys right now, so we * will ignore this if requested. */ (void)export_session_key; @@ -1642,10 +1653,10 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only, gpgsm_assuan_simple_command (gpgsm, "GETINFO agent-check", NULL, NULL); /* Always send list-mode option because RESET does not reset it. */ - if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) + if (gpgrt_asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) return gpg_error_from_syserror (); err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL); - free (line); + gpgrt_free (line); if (err) return err; @@ -1726,10 +1737,10 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only, list_mode |= 2; /* Always send list-mode option because RESET does not reset it. */ - if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) + if (gpgrt_asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0) return gpg_error_from_syserror (); err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL); - free (line); + gpgrt_free (line); if (err) return err; @@ -1860,10 +1871,11 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out, can reset any previously set value in case the default is requested. */ - if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0) + if (gpgrt_asprintf (&assuan_cmd, + "OPTION include-certs %i", include_certs) < 0) return gpg_error_from_syserror (); err = gpgsm_assuan_simple_command (gpgsm, assuan_cmd, NULL, NULL); - free (assuan_cmd); + gpgrt_free (assuan_cmd); if (err) return err; } @@ -2048,7 +2060,7 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags) if (!key || !key->subkeys || !key->subkeys->fpr) return gpg_error (GPG_ERR_INV_CERT_OBJ); - if (asprintf (&line, "PASSWD -- %s", key->subkeys->fpr) < 0) + if (gpgrt_asprintf (&line, "PASSWD -- %s", key->subkeys->fpr) < 0) return gpg_error_from_syserror (); gpgsm_clear_fd (gpgsm, OUTPUT_FD); @@ -2057,7 +2069,7 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags) gpgsm->inline_data = NULL; err = start (gpgsm, line); - free (line); + gpgrt_free (line); return err; } @@ -2087,7 +2099,6 @@ struct engine_ops _gpgme_engine_ops_gpgsm = gpgsm_set_locale, NULL, /* set_protocol */ gpgsm_decrypt, - gpgsm_decrypt, gpgsm_delete, /* decrypt_verify */ NULL, /* edit */ gpgsm_encrypt, @@ -2098,6 +2109,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm = gpgsm_import, gpgsm_keylist, gpgsm_keylist_ext, + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ gpgsm_sign, diff --git a/src/engine-spawn.c b/src/engine-spawn.c index 1cd4421..9d587cc 100644 --- a/src/engine-spawn.c +++ b/src/engine-spawn.c @@ -449,7 +449,6 @@ struct engine_ops _gpgme_engine_ops_spawn = NULL, /* set_locale */ NULL, /* set_protocol */ NULL, /* decrypt */ - NULL, /* decrypt_verify */ NULL, /* delete */ NULL, /* edit */ NULL, /* encrypt */ @@ -460,6 +459,7 @@ struct engine_ops _gpgme_engine_ops_spawn = NULL, /* import */ NULL, /* keylist */ NULL, /* keylist_ext */ + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ NULL, /* sign */ diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index ee7b1d2..20a8abf 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -316,7 +316,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_display) { - if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0) + if (gpgrt_asprintf (&optstr, "OPTION display=%s", dft_display) < 0) { err = gpg_error_from_syserror (); free (dft_display); @@ -326,7 +326,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -350,14 +350,14 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir, ways, e.g., when /dev/pts is not accessible under chroot. */ if (!rc) { - if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0) { err = gpg_error_from_syserror (); goto leave; } err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; @@ -366,7 +366,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_ttytype) { - if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0) + if (gpgrt_asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype)< 0) { err = gpg_error_from_syserror (); free (dft_ttytype); @@ -376,7 +376,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir, err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); if (err) goto leave; } @@ -441,13 +441,13 @@ uiserver_set_locale (void *engine, int category, const char *value) if (!value) return 0; - if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) + if (gpgrt_asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0) err = gpg_error_from_syserror (); else { err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); - free (optstr); + gpgrt_free (optstr); } return err; @@ -959,14 +959,16 @@ uiserver_reset (void *engine) static gpgme_error_t -_uiserver_decrypt (void *engine, int verify, - gpgme_data_t ciph, gpgme_data_t plain, - int export_session_key, const char *override_session_key) +uiserver_decrypt (void *engine, + gpgme_decrypt_flags_t flags, + gpgme_data_t ciph, gpgme_data_t plain, + int export_session_key, const char *override_session_key) { engine_uiserver_t uiserver = engine; gpgme_error_t err; const char *protocol; char *cmd; + int verify = !!(flags & GPGME_DECRYPT_VERIFY); (void)override_session_key; /* Fixme: We need to see now to add this * to the UI server protocol */ @@ -982,7 +984,7 @@ _uiserver_decrypt (void *engine, int verify, else return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); - if (asprintf (&cmd, "DECRYPT%s%s%s", protocol, + if (gpgrt_asprintf (&cmd, "DECRYPT%s%s%s", protocol, verify ? "" : " --no-verify", export_session_key ? " --export-session-key" : "") < 0) return gpg_error_from_syserror (); @@ -992,44 +994,25 @@ _uiserver_decrypt (void *engine, int verify, map_data_enc (uiserver->input_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return gpg_error (GPG_ERR_GENERAL); /* FIXME */ } uiserver->output_cb.data = plain; err = uiserver_set_fd (uiserver, OUTPUT_FD, 0); if (err) { - free (cmd); + gpgrt_free (cmd); return gpg_error (GPG_ERR_GENERAL); /* FIXME */ } uiserver->inline_data = NULL; err = start (engine, cmd); - free (cmd); + gpgrt_free (cmd); return err; } static gpgme_error_t -uiserver_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain, - int export_session_key, const char *override_session_key) -{ - return _uiserver_decrypt (engine, 0, ciph, plain, - export_session_key, override_session_key); -} - - -static gpgme_error_t -uiserver_decrypt_verify (void *engine, gpgme_data_t ciph, gpgme_data_t plain, - int export_session_key, - const char *override_session_key) -{ - return _uiserver_decrypt (engine, 1, ciph, plain, - export_session_key, override_session_key); -} - - -static gpgme_error_t set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[]) { gpgme_error_t err = 0; @@ -1114,7 +1097,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!recp || plain || ciph) return gpg_error (GPG_ERR_INV_VALUE); - if (asprintf (&cmd, "PREP_ENCRYPT%s%s", protocol, + if (gpgrt_asprintf (&cmd, "PREP_ENCRYPT%s%s", protocol, (flags & GPGME_ENCRYPT_EXPECT_SIGN) ? " --expect-sign" : "") < 0) return gpg_error_from_syserror (); @@ -1124,7 +1107,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!plain || !ciph) return gpg_error (GPG_ERR_INV_VALUE); - if (asprintf (&cmd, "ENCRYPT%s", protocol) < 0) + if (gpgrt_asprintf (&cmd, "ENCRYPT%s", protocol) < 0) return gpg_error_from_syserror (); } @@ -1135,7 +1118,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, map_data_enc (uiserver->input_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } } @@ -1147,7 +1130,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, : map_data_enc (uiserver->output_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } } @@ -1159,13 +1142,13 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, err = set_recipients (uiserver, recp); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } } err = start (uiserver, cmd); - free (cmd); + gpgrt_free (cmd); return err; } @@ -1195,7 +1178,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, else return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); - if (asprintf (&cmd, "SIGN%s%s", protocol, + if (gpgrt_asprintf (&cmd, "SIGN%s%s", protocol, (mode == GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0) return gpg_error_from_syserror (); @@ -1220,10 +1203,10 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, err = gpg_error (GPG_ERR_INV_VALUE); gpgme_key_unref (key); if (err) - { - free (cmd); - return err; - } + { + gpgrt_free (cmd); + return err; + } } uiserver->input_cb.data = in; @@ -1231,7 +1214,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, map_data_enc (uiserver->input_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } uiserver->output_cb.data = out; @@ -1239,13 +1222,13 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, : map_data_enc (uiserver->output_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } uiserver->inline_data = NULL; err = start (uiserver, cmd); - free (cmd); + gpgrt_free (cmd); return err; } @@ -1274,7 +1257,7 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, else return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); - if (asprintf (&cmd, "VERIFY%s", protocol) < 0) + if (gpgrt_asprintf (&cmd, "VERIFY%s", protocol) < 0) return gpg_error_from_syserror (); uiserver->input_cb.data = sig; @@ -1282,7 +1265,7 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, map_data_enc (uiserver->input_cb.data)); if (err) { - free (cmd); + gpgrt_free (cmd); return err; } if (plaintext) @@ -1302,7 +1285,7 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, if (!err) err = start (uiserver, cmd); - free (cmd); + gpgrt_free (cmd); return err; } @@ -1383,7 +1366,6 @@ struct engine_ops _gpgme_engine_ops_uiserver = uiserver_set_locale, uiserver_set_protocol, uiserver_decrypt, - uiserver_decrypt_verify, NULL, /* delete */ NULL, /* edit */ uiserver_encrypt, @@ -1394,6 +1376,7 @@ struct engine_ops _gpgme_engine_ops_uiserver = NULL, /* import */ NULL, /* keylist */ NULL, /* keylist_ext */ + NULL, /* keylist_data */ NULL, /* keysign */ NULL, /* tofu_policy */ uiserver_sign, diff --git a/src/engine.c b/src/engine.c index 75d9ff7..278916d 100644 --- a/src/engine.c +++ b/src/engine.c @@ -652,7 +652,9 @@ _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol) gpgme_error_t -_gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph, +_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) { @@ -662,29 +664,12 @@ _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph, if (!engine->ops->decrypt) return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - return (*engine->ops->decrypt) (engine->engine, ciph, plain, + return (*engine->ops->decrypt) (engine->engine, flags, ciph, plain, export_session_key, override_session_key); } gpgme_error_t -_gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph, - gpgme_data_t plain, int export_session_key, - const char *override_session_key) -{ - if (!engine) - return gpg_error (GPG_ERR_INV_VALUE); - - if (!engine->ops->decrypt_verify) - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - - return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain, - export_session_key, - override_session_key); -} - - -gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, int allow_secret) { @@ -876,6 +861,19 @@ _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[], 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, diff --git a/src/engine.h b/src/engine.h index 29d2f25..dd0ef9c 100644 --- a/src/engine.h +++ b/src/engine.h @@ -25,8 +25,9 @@ #include "gpgme.h" /* Flags used by the EXTRAFLAGS arg of _gpgme_engine_op_genkey. */ -#define GENKEY_EXTRAFLAG_ARMOR 1 -#define GENKEY_EXTRAFLAG_REVOKE 2 +#define GENKEY_EXTRAFLAG_ARMOR 1 +#define GENKEY_EXTRAFLAG_REVOKE 2 +#define GENKEY_EXTRAFLAG_SETPRIMARY 4 struct engine; @@ -82,16 +83,12 @@ gpgme_error_t _gpgme_engine_set_colon_line_handler (engine_t engine, engine_colon_line_handler_t fnc, void *fnc_value); -gpgme_error_t _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph, +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); -gpgme_error_t _gpgme_engine_op_decrypt_verify (engine_t engine, - gpgme_data_t ciph, - gpgme_data_t plain, - int export_session_key, - const char *override_session_key - ); gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key, int allow_secret); gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type, @@ -148,6 +145,8 @@ gpgme_error_t _gpgme_engine_op_keylist_ext (engine_t engine, int reserved, gpgme_keylist_mode_t mode, int engine_flags); +gpgme_error_t _gpgme_engine_op_keylist_data (engine_t engine, + gpgme_data_t 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, diff --git a/src/funopen.c b/src/funopen.c deleted file mode 100644 index b722020..0000000 --- a/src/funopen.c +++ /dev/null @@ -1,63 +0,0 @@ -/* funopen.c - Replacement for funopen. - Copyright (C) 2004 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. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> - - -/* Replacement for the *BSD function: - - FILE *funopen (void *cookie, - int (*readfn)(void *, char *, int), - int (*writefn)(void *, const char *, int), - fpos_t (*seekfn)(void *, fpos_t, int), - int (*closefn)(void *)); - - The functions to provide my either be NULL if not required or - similar to the unistd function with the exception of using the - cookie instead of the file descriptor. -*/ - - -#ifdef HAVE_FOPENCOOKIE -FILE * -_gpgme_funopen(void *cookie, - cookie_read_function_t *readfn, - cookie_write_function_t *writefn, - cookie_seek_function_t *seekfn, - cookie_close_function_t *closefn) -{ - cookie_io_functions_t io = { NULL }; - - io.read = readfn; - io.write = writefn; - io.seek = seekfn; - io.close = closefn; - - return fopencookie (cookie, - readfn ? ( writefn ? "rw" : "r" ) - : ( writefn ? "w" : ""), io); -} -#else -#error No known way to implement funopen. -#endif diff --git a/src/genkey.c b/src/genkey.c index ea3f1ea..710b58f 100644 --- a/src/genkey.c +++ b/src/genkey.c @@ -489,7 +489,7 @@ gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo, static gpgme_error_t -addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke, +addrevuid_start (gpgme_ctx_t ctx, int synchronous, int extraflags, gpgme_key_t key, const char *userid, unsigned int flags) { gpgme_error_t err; @@ -512,7 +512,7 @@ addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke, if (err) return err; - opd->uidmode = revoke? 2 : 1; + opd->uidmode = extraflags? 2 : 1; _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx); @@ -528,7 +528,7 @@ addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke, userid, NULL, 0, 0, key, flags, NULL, - revoke? GENKEY_EXTRAFLAG_REVOKE : 0, + extraflags, NULL, NULL); } @@ -584,7 +584,7 @@ gpgme_op_revuid_start (gpgme_ctx_t ctx, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG)); - err = addrevuid_start (ctx, 0, 1, key, userid, flags); + err = addrevuid_start (ctx, 0, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags); return TRACE_ERR (err); } @@ -601,8 +601,60 @@ gpgme_op_revuid (gpgme_ctx_t ctx, if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG)); - err = addrevuid_start (ctx, 1, 1, key, userid, flags); + err = addrevuid_start (ctx, 1, GENKEY_EXTRAFLAG_REVOKE, key, userid, flags); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); } + + +/* Set a flag on the USERID of KEY. The only supported flag right now + * is "primary" to mark the primary key. */ +static gpg_error_t +set_uid_flag (gpgme_ctx_t ctx, int synchronous, + gpgme_key_t key, const char *userid, + const char *name, const char *value) +{ + gpgme_error_t err; + + TRACE_BEG4 (DEBUG_CTX, "gpgme_op_set_uid_flag", ctx, + "%d uid='%s' '%s'='%s'", synchronous, userid, name, value); + + if (!ctx || !name || !key || !userid) + return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG)); + + if (!strcmp (name, "primary")) + { + if (value) + err = gpg_error (GPG_ERR_INV_ARG); + else + err = addrevuid_start (ctx, synchronous, + GENKEY_EXTRAFLAG_SETPRIMARY, key, userid, 0); + } + else + return err = gpg_error (GPG_ERR_UNKNOWN_NAME); + + if (synchronous && !err) + err = _gpgme_wait_one (ctx); + return TRACE_ERR (err); +} + + +/* See set_uid_flag. */ +gpgme_error_t +gpgme_op_set_uid_flag_start (gpgme_ctx_t ctx, + gpgme_key_t key, const char *userid, + const char *name, const char *value) +{ + return set_uid_flag (ctx, 0, key, userid, name, value); +} + + +/* See set_uid_flag. Thsi is the synchronous variant. */ +gpgme_error_t +gpgme_op_set_uid_flag (gpgme_ctx_t ctx, + gpgme_key_t key, const char *userid, + const char *name, const char *value) +{ + return set_uid_flag (ctx, 1, key, userid, name, value); +} diff --git a/src/gpgme.c b/src/gpgme.c index cf767c7..2b196a2 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -508,6 +508,10 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value) 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; @@ -544,6 +548,10 @@ 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":""; diff --git a/src/gpgme.def b/src/gpgme.def index 0d3ce74..51053cd 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -177,8 +177,8 @@ EXPORTS gpgme_io_read @136 gpgme_io_write @137 - gpgme_result_ref @138 - gpgme_result_unref @139 + gpgme_result_ref @138 + gpgme_result_unref @139 gpgme_op_import_keys @140 gpgme_op_import_keys_start @141 @@ -253,5 +253,14 @@ EXPORTS gpgme_op_query_swdb_result @190 gpgme_get_ctx_flag @191 + + gpgme_op_keylist_from_data_start @192 + + gpgme_op_set_uid_flag_start @193 + gpgme_op_set_uid_flag @194 + + gpgme_op_decrypt_ext @195 + gpgme_op_decrypt_ext_start @196 + ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 7cfe8f6..24b21e7 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1,6 +1,6 @@ /* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*- * Copyright (C) 2000 Werner Koch (dd9jn) - * Copyright (C) 2001-2016 g10 Code GmbH + * Copyright (C) 2001-2017 g10 Code GmbH * * This file is part of GPGME. * @@ -294,24 +294,6 @@ typedef enum gpgme_hash_algo_t; -/* The possible signature stati. Deprecated, use error value in sig - status. */ -typedef enum - { - GPGME_SIG_STAT_NONE = 0, - GPGME_SIG_STAT_GOOD = 1, - GPGME_SIG_STAT_BAD = 2, - GPGME_SIG_STAT_NOKEY = 3, - GPGME_SIG_STAT_NOSIG = 4, - GPGME_SIG_STAT_ERROR = 5, - GPGME_SIG_STAT_DIFF = 6, - GPGME_SIG_STAT_GOOD_EXP = 7, - GPGME_SIG_STAT_GOOD_EXPKEY = 8 - } -_gpgme_sig_stat_t; -typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED(0,4); - - /* The available signature modes. */ typedef enum { @@ -322,47 +304,6 @@ typedef enum gpgme_sig_mode_t; -/* The available key and signature attributes. Deprecated, use the - individual result structures instead. */ -typedef enum - { - GPGME_ATTR_KEYID = 1, - GPGME_ATTR_FPR = 2, - GPGME_ATTR_ALGO = 3, - GPGME_ATTR_LEN = 4, - GPGME_ATTR_CREATED = 5, - GPGME_ATTR_EXPIRE = 6, - GPGME_ATTR_OTRUST = 7, - GPGME_ATTR_USERID = 8, - GPGME_ATTR_NAME = 9, - GPGME_ATTR_EMAIL = 10, - GPGME_ATTR_COMMENT = 11, - GPGME_ATTR_VALIDITY = 12, - GPGME_ATTR_LEVEL = 13, - GPGME_ATTR_TYPE = 14, - GPGME_ATTR_IS_SECRET = 15, - GPGME_ATTR_KEY_REVOKED = 16, - GPGME_ATTR_KEY_INVALID = 17, - GPGME_ATTR_UID_REVOKED = 18, - GPGME_ATTR_UID_INVALID = 19, - GPGME_ATTR_KEY_CAPS = 20, - GPGME_ATTR_CAN_ENCRYPT = 21, - GPGME_ATTR_CAN_SIGN = 22, - GPGME_ATTR_CAN_CERTIFY = 23, - GPGME_ATTR_KEY_EXPIRED = 24, - GPGME_ATTR_KEY_DISABLED = 25, - GPGME_ATTR_SERIAL = 26, - GPGME_ATTR_ISSUER = 27, - GPGME_ATTR_CHAINID = 28, - GPGME_ATTR_SIG_STATUS = 29, - GPGME_ATTR_ERRTOK = 30, - GPGME_ATTR_SIG_SUMMARY = 31, - GPGME_ATTR_SIG_CLASS = 32 - } -_gpgme_attr_t; -typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED(0,4); - - /* The available validities for a trust item or key. */ typedef enum { @@ -447,128 +388,15 @@ typedef unsigned int gpgme_export_mode_t; #define GPGME_AUDITLOG_WITH_HELP 128 -/* The possible stati for gpgme_op_edit. The use of that function and - * these status codes are deprecated in favor of gpgme_op_interact. */ -typedef enum - { - GPGME_STATUS_EOF = 0, - /* mkstatus processing starts here */ - GPGME_STATUS_ENTER = 1, - GPGME_STATUS_LEAVE = 2, - GPGME_STATUS_ABORT = 3, - - GPGME_STATUS_GOODSIG = 4, - GPGME_STATUS_BADSIG = 5, - GPGME_STATUS_ERRSIG = 6, - - GPGME_STATUS_BADARMOR = 7, - - GPGME_STATUS_RSA_OR_IDEA = 8, /* (legacy) */ - GPGME_STATUS_KEYEXPIRED = 9, - GPGME_STATUS_KEYREVOKED = 10, - - GPGME_STATUS_TRUST_UNDEFINED = 11, - GPGME_STATUS_TRUST_NEVER = 12, - GPGME_STATUS_TRUST_MARGINAL = 13, - GPGME_STATUS_TRUST_FULLY = 14, - GPGME_STATUS_TRUST_ULTIMATE = 15, - - GPGME_STATUS_SHM_INFO = 16, /* (legacy) */ - GPGME_STATUS_SHM_GET = 17, /* (legacy) */ - GPGME_STATUS_SHM_GET_BOOL = 18, /* (legacy) */ - GPGME_STATUS_SHM_GET_HIDDEN = 19, /* (legacy) */ - - GPGME_STATUS_NEED_PASSPHRASE = 20, - GPGME_STATUS_VALIDSIG = 21, - GPGME_STATUS_SIG_ID = 22, - GPGME_STATUS_ENC_TO = 23, - GPGME_STATUS_NODATA = 24, - GPGME_STATUS_BAD_PASSPHRASE = 25, - GPGME_STATUS_NO_PUBKEY = 26, - GPGME_STATUS_NO_SECKEY = 27, - GPGME_STATUS_NEED_PASSPHRASE_SYM = 28, - GPGME_STATUS_DECRYPTION_FAILED = 29, - GPGME_STATUS_DECRYPTION_OKAY = 30, - GPGME_STATUS_MISSING_PASSPHRASE = 31, - GPGME_STATUS_GOOD_PASSPHRASE = 32, - GPGME_STATUS_GOODMDC = 33, - GPGME_STATUS_BADMDC = 34, - GPGME_STATUS_ERRMDC = 35, - GPGME_STATUS_IMPORTED = 36, - GPGME_STATUS_IMPORT_OK = 37, - GPGME_STATUS_IMPORT_PROBLEM = 38, - GPGME_STATUS_IMPORT_RES = 39, - GPGME_STATUS_FILE_START = 40, - GPGME_STATUS_FILE_DONE = 41, - GPGME_STATUS_FILE_ERROR = 42, - - GPGME_STATUS_BEGIN_DECRYPTION = 43, - GPGME_STATUS_END_DECRYPTION = 44, - GPGME_STATUS_BEGIN_ENCRYPTION = 45, - GPGME_STATUS_END_ENCRYPTION = 46, - - GPGME_STATUS_DELETE_PROBLEM = 47, - GPGME_STATUS_GET_BOOL = 48, - GPGME_STATUS_GET_LINE = 49, - GPGME_STATUS_GET_HIDDEN = 50, - GPGME_STATUS_GOT_IT = 51, - GPGME_STATUS_PROGRESS = 52, - GPGME_STATUS_SIG_CREATED = 53, - GPGME_STATUS_SESSION_KEY = 54, - GPGME_STATUS_NOTATION_NAME = 55, - GPGME_STATUS_NOTATION_DATA = 56, - GPGME_STATUS_POLICY_URL = 57, - GPGME_STATUS_BEGIN_STREAM = 58, /* (legacy) */ - GPGME_STATUS_END_STREAM = 59, /* (legacy) */ - GPGME_STATUS_KEY_CREATED = 60, - GPGME_STATUS_USERID_HINT = 61, - GPGME_STATUS_UNEXPECTED = 62, - GPGME_STATUS_INV_RECP = 63, - GPGME_STATUS_NO_RECP = 64, - GPGME_STATUS_ALREADY_SIGNED = 65, - GPGME_STATUS_SIGEXPIRED = 66, /* (legacy) */ - GPGME_STATUS_EXPSIG = 67, - GPGME_STATUS_EXPKEYSIG = 68, - GPGME_STATUS_TRUNCATED = 69, - GPGME_STATUS_ERROR = 70, - GPGME_STATUS_NEWSIG = 71, - GPGME_STATUS_REVKEYSIG = 72, - GPGME_STATUS_SIG_SUBPACKET = 73, - GPGME_STATUS_NEED_PASSPHRASE_PIN = 74, - GPGME_STATUS_SC_OP_FAILURE = 75, - GPGME_STATUS_SC_OP_SUCCESS = 76, - GPGME_STATUS_CARDCTRL = 77, - GPGME_STATUS_BACKUP_KEY_CREATED = 78, - GPGME_STATUS_PKA_TRUST_BAD = 79, - GPGME_STATUS_PKA_TRUST_GOOD = 80, - GPGME_STATUS_PLAINTEXT = 81, - GPGME_STATUS_INV_SGNR = 82, - GPGME_STATUS_NO_SGNR = 83, - GPGME_STATUS_SUCCESS = 84, - GPGME_STATUS_DECRYPTION_INFO = 85, - GPGME_STATUS_PLAINTEXT_LENGTH = 86, - GPGME_STATUS_MOUNTPOINT = 87, - GPGME_STATUS_PINENTRY_LAUNCHED = 88, - GPGME_STATUS_ATTRIBUTE = 89, - GPGME_STATUS_BEGIN_SIGNING = 90, - GPGME_STATUS_KEY_NOT_CREATED = 91, - GPGME_STATUS_INQUIRE_MAXLEN = 92, - GPGME_STATUS_FAILURE = 93, - GPGME_STATUS_KEY_CONSIDERED = 94, - GPGME_STATUS_TOFU_USER = 95, - GPGME_STATUS_TOFU_STATS = 96, - GPGME_STATUS_TOFU_STATS_LONG = 97, - GPGME_STATUS_NOTATION_FLAGS = 98 - } -gpgme_status_code_t; - - /* The available signature notation flags. */ #define GPGME_SIG_NOTATION_HUMAN_READABLE 1 #define GPGME_SIG_NOTATION_CRITICAL 2 typedef unsigned int gpgme_sig_notation_flags_t; +/* An object to hold information about notation data. This structure + * shall be considered read-only and an application must not allocate + * such a structure on its own. */ struct _gpgme_sig_notation { struct _gpgme_sig_notation *next; @@ -606,7 +434,9 @@ typedef struct _gpgme_sig_notation *gpgme_sig_notation_t; * Public structures. */ -/* The engine information structure. */ +/* The engine information structure. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_engine_info { struct _gpgme_engine_info *next; @@ -629,7 +459,9 @@ struct _gpgme_engine_info typedef struct _gpgme_engine_info *gpgme_engine_info_t; -/* An object with TOFU information. */ +/* An object with TOFU information. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_tofu_info { struct _gpgme_tofu_info *next; @@ -666,7 +498,9 @@ struct _gpgme_tofu_info typedef struct _gpgme_tofu_info *gpgme_tofu_info_t; -/* A subkey from a key. */ +/* A subkey from a key. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_subkey { struct _gpgme_subkey *next; @@ -704,8 +538,11 @@ struct _gpgme_subkey /* True if the secret key is stored on a smart card. */ unsigned int is_cardkey : 1; + /* True if the key is compliant to the de-vs mode. */ + unsigned int is_de_vs : 1; + /* Internal to GPGME, do not use. */ - unsigned int _unused : 21; + unsigned int _unused : 20; /* Public key algorithm supported by this subkey. */ gpgme_pubkey_algo_t pubkey_algo; @@ -740,7 +577,9 @@ struct _gpgme_subkey typedef struct _gpgme_subkey *gpgme_subkey_t; -/* A signature on a user ID. */ +/* A signature on a user ID. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_key_sig { struct _gpgme_key_sig *next; @@ -809,7 +648,9 @@ struct _gpgme_key_sig typedef struct _gpgme_key_sig *gpgme_key_sig_t; -/* An user ID from a key. */ +/* An user ID from a key. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_user_id { struct _gpgme_user_id *next; @@ -821,7 +662,10 @@ struct _gpgme_user_id unsigned int invalid : 1; /* Internal to GPGME, do not use. */ - unsigned int _unused : 30; + unsigned int _unused : 25; + + /* Origin of this user ID. */ + unsigned int origin : 5; /* The validity of the user ID. */ gpgme_validity_t validity; @@ -852,11 +696,16 @@ struct _gpgme_user_id /* The malloced TOFU information or NULL. */ gpgme_tofu_info_t tofu; + + /* Time of the last refresh of thsi user id. 0 if unknown. */ + unsigned long last_update; }; typedef struct _gpgme_user_id *gpgme_user_id_t; -/* A key from the keyring. */ +/* A key from the keyring. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_key { /* Internal to GPGME, do not use. */ @@ -893,7 +742,10 @@ struct _gpgme_key unsigned int is_qualified : 1; /* Internal to GPGME, do not use. */ - unsigned int _unused : 22; + unsigned int _unused : 17; + + /* Origin of this key. */ + unsigned int origin : 5; /* This is the protocol supported by this key. */ gpgme_protocol_t protocol; @@ -933,11 +785,16 @@ struct _gpgme_key * this is a copy of the FPR of the first subkey. We need it here * to allow for an incomplete key object. */ char *fpr; + + /* Time of the last refresh of the entire key. 0 if unknown. */ + unsigned long last_update; }; typedef struct _gpgme_key *gpgme_key_t; -/* An invalid key object. */ +/* An invalid key object. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_invalid_key { struct _gpgme_invalid_key *next; @@ -976,13 +833,6 @@ typedef gpgme_error_t (*gpgme_interact_cb_t) (void *opaque, const char *keyword, const char *args, int fd); -/* The callback type used by the deprecated functions gpgme_op_edit - * and gpgme_op_card_edit. */ -typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque, - gpgme_status_code_t status, - const char *args, int fd); - - /* @@ -1122,33 +972,6 @@ unsigned int gpgme_signers_count (const gpgme_ctx_t ctx); /* Return the SEQth signer's key in CTX. */ gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq); -/* Retrieve the signature status of signature IDX in CTX after a - successful verify operation in R_STAT (if non-null). The creation - time stamp of the signature is returned in R_CREATED (if non-null). - The function returns a string containing the fingerprint. - Deprecated, use verify result directly. */ -const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, - _gpgme_sig_stat_t *r_stat, - time_t *r_created) _GPGME_DEPRECATED(0,4); - -/* Retrieve certain attributes of a signature. IDX is the index - number of the signature after a successful verify operation. WHAT - is an attribute where GPGME_ATTR_EXPIRE is probably the most useful - one. WHATIDX is to be passed as 0 for most attributes . */ -unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx, - _gpgme_attr_t what, int whatidx) - _GPGME_DEPRECATED(0,4); -const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx, - _gpgme_attr_t what, int whatidx) - _GPGME_DEPRECATED(0,4); - - -/* Get the key used to create signature IDX in CTX and return it in - R_KEY. */ -gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) - _GPGME_DEPRECATED(0,4); - - /* Clear all notation data from the context. */ void gpgme_sig_notation_clear (gpgme_ctx_t ctx); @@ -1360,15 +1183,6 @@ gpg_error_t gpgme_data_set_flag (gpgme_data_t dh, gpgme_data_type_t gpgme_data_identify (gpgme_data_t dh, int reserved); -/* Create a new data buffer which retrieves the data from the callback - function READ_CB. Deprecated, please use gpgme_data_new_from_cbs - instead. */ -gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, - int (*read_cb) (void*,char *, - size_t,size_t*), - void *read_cb_value) - _GPGME_DEPRECATED(0,4); - /* Create a new data buffer filled with the content of file FNAME. COPY must be non-zero. For delayed read, please use gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */ @@ -1383,9 +1197,8 @@ gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname, FILE *fp, @API__OFF_T@ offset, size_t length); -/* Reset the read pointer in DH. Deprecated, please use - gpgme_data_seek instead. */ -gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED(0,4); +/* Convenience function to do a gpgme_data_seek (dh, 0, SEEK_SET). */ +gpgme_error_t gpgme_data_rewind (gpgme_data_t dh); @@ -1409,46 +1222,15 @@ void gpgme_key_ref (gpgme_key_t key); void gpgme_key_unref (gpgme_key_t key); void gpgme_key_release (gpgme_key_t key); -/* Return the value of the attribute WHAT of KEY, which has to be - representable by a string. IDX specifies the sub key or user ID - for attributes related to sub keys or user IDs. Deprecated, use - key structure directly instead. */ -const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - -/* Return the value of the attribute WHAT of KEY, which has to be - representable by an unsigned integer. IDX specifies the sub key or - user ID for attributes related to sub keys or user IDs. - Deprecated, use key structure directly instead. */ -unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - -/* Return the value of the attribute WHAT of a signature on user ID - UID_IDX in KEY, which has to be representable by a string. IDX - specifies the signature. Deprecated, use key structure directly - instead. */ -const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx, - _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - -/* Return the value of the attribute WHAT of a signature on user ID - UID_IDX in KEY, which has to be representable by an unsigned - integer string. IDX specifies the signature. Deprecated, use key - structure directly instead. */ -unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, - _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - /* * Encryption. */ +/* An object to return results from an encryption operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_encrypt_result { /* The list of invalid recipients. */ @@ -1467,7 +1249,9 @@ typedef enum GPGME_ENCRYPT_PREPARE = 4, GPGME_ENCRYPT_EXPECT_SIGN = 8, GPGME_ENCRYPT_NO_COMPRESS = 16, - GPGME_ENCRYPT_SYMMETRIC = 32 + GPGME_ENCRYPT_SYMMETRIC = 32, + GPGME_ENCRYPT_THROW_KEYIDS = 64, + GPGME_ENCRYPT_WRAP = 128 } gpgme_encrypt_flags_t; @@ -1497,6 +1281,9 @@ gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], * Decryption. */ +/* An object to hold information about a recipient. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_recipient { struct _gpgme_recipient *next; @@ -1515,6 +1302,9 @@ struct _gpgme_recipient }; typedef struct _gpgme_recipient *gpgme_recipient_t; +/* An object to return results from a decryption operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_decrypt_result { char *unsupported_algorithm; @@ -1540,6 +1330,14 @@ typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t; /* Retrieve a pointer to the result of the decrypt operation. */ gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx); +/* The valid decryption flags. */ +typedef enum + { + GPGME_DECRYPT_VERIFY = 1, + GPGME_DECRYPT_UNWRAP = 128 + } +gpgme_decrypt_flags_t; + /* Decrypt ciphertext CIPHER within CTX and store the resulting plaintext in PLAIN. */ gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, @@ -1555,11 +1353,27 @@ gpgme_error_t gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_error_t gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain); +/* Decrypt ciphertext CIPHER within CTX and store the resulting + * plaintext in PLAIN. With the flag GPGME_DECRYPT_VERIFY also do a + * signature verification pn the plaintext. */ +gpgme_error_t gpgme_op_decrypt_ext_start (gpgme_ctx_t ctx, + gpgme_decrypt_flags_t flags, + gpgme_data_t cipher, + gpgme_data_t plain); +gpgme_error_t gpgme_op_decrypt_ext (gpgme_ctx_t ctx, + gpgme_decrypt_flags_t flags, + gpgme_data_t cipher, + gpgme_data_t plain); + + /* * Signing. */ +/* An object with signatures data. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_new_signature { struct _gpgme_new_signature *next; @@ -1595,6 +1409,10 @@ struct _gpgme_new_signature }; typedef struct _gpgme_new_signature *gpgme_new_signature_t; + +/* An object to return results from a signing operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_sign_result { /* The list of invalid signers. */ @@ -1638,6 +1456,9 @@ typedef enum gpgme_sigsum_t; +/* An object to hold the verification status of a signature. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_signature { struct _gpgme_signature *next; @@ -1690,6 +1511,9 @@ struct _gpgme_signature }; typedef struct _gpgme_signature *gpgme_signature_t; +/* An object to return the results of a verify operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_verify_result { gpgme_signature_t signatures; @@ -1723,6 +1547,9 @@ gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, #define GPGME_IMPORT_SECRET 16 /* The key contained a secret key. */ +/* An object to hold results for one imported key. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_import_status { struct _gpgme_import_status *next; @@ -1741,7 +1568,9 @@ struct _gpgme_import_status }; typedef struct _gpgme_import_status *gpgme_import_status_t; -/* Import result object. */ +/* Import result object. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_import_result { /* Number of considered keys. */ @@ -1797,8 +1626,6 @@ gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx); /* Import the key in KEYDATA into the keyring. */ gpgme_error_t gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata); gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata); -gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, - int *nr) _GPGME_DEPRECATED(0,4); /* Import the keys from the array KEYS into the keyring. */ gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]); @@ -1848,7 +1675,11 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx, #define GPGME_CREATE_WANTPUB (1 << 10) /* Return the public key. */ #define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */ #define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */ +#define GPGME_CREATE_NOEXPIRE (1 << 13) /* Create w/o expiration. */ +/* An object to return result from a key generation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_genkey_result { /* A primary key was generated. */ @@ -1929,6 +1760,13 @@ gpgme_error_t gpgme_op_revuid (gpgme_ctx_t ctx, gpgme_key_t key, const char *userid, unsigned int reserved); +/* Set a flag on the USERID of KEY. See the manual for supported flags. */ +gpgme_error_t gpgme_op_set_uid_flag_start (gpgme_ctx_t ctx, + gpgme_key_t key, const char *userid, + const char *name, const char *value); +gpgme_error_t gpgme_op_set_uid_flag (gpgme_ctx_t ctx, + gpgme_key_t key, const char *userid, + const char *name, const char *value); /* Retrieve a pointer to the result of a genkey, createkey, or @@ -1989,21 +1827,6 @@ gpgme_error_t gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, void *fnc_value, gpgme_data_t out); -gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, - gpgme_edit_cb_t fnc, void *fnc_value, - gpgme_data_t out) _GPGME_DEPRECATED(1,7); -gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key, - gpgme_edit_cb_t fnc, void *fnc_value, - gpgme_data_t out) _GPGME_DEPRECATED(1,7); -gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, - gpgme_edit_cb_t fnc, void *fnc_value, - gpgme_data_t out) - _GPGME_DEPRECATED(1,7); -gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key, - gpgme_edit_cb_t fnc, void *fnc_value, - gpgme_data_t out) - _GPGME_DEPRECATED(1,7); - /* Set the Tofu policy of KEY to POLCIY. */ gpgme_error_t gpgme_op_tofu_policy_start (gpgme_ctx_t ctx, @@ -2020,6 +1843,9 @@ gpgme_error_t gpgme_op_tofu_policy (gpgme_ctx_t ctx, * Key listing */ +/* An object to return results from a key listing operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_keylist_result { unsigned int truncated : 1; @@ -2033,20 +1859,31 @@ typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t; gpgme_keylist_result_t gpgme_op_keylist_result (gpgme_ctx_t ctx); /* Start a keylist operation within CTX, searching for keys which - match PATTERN. If SECRET_ONLY is true, only secret keys are - returned. */ + * match PATTERN. If SECRET_ONLY is true, only secret keys are + * returned. */ gpgme_error_t gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only); gpgme_error_t gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[], int secret_only, int reserved); +/* List the keys contained in DATA. */ +gpgme_error_t gpgme_op_keylist_from_data_start (gpgme_ctx_t ctx, + gpgme_data_t data, + int reserved); + /* Return the next key from the keylist in R_KEY. */ gpgme_error_t gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key); /* Terminate a pending keylist operation within CTX. */ gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx); + + +/* + * Protecting keys + */ + /* Change the passphrase for KEY. FLAGS is reserved for future use and must be passed as 0. */ gpgme_error_t gpgme_op_passwd_start (gpgme_ctx_t ctx, gpgme_key_t key, @@ -2060,6 +1897,9 @@ gpgme_error_t gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key, * Trust items and operations. */ +/* An object to hold data of a trust item. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_trust_item { /* Internal to GPGME, do not use. */ @@ -2113,26 +1953,6 @@ void gpgme_trust_item_ref (gpgme_trust_item_t item); item is destroyed. */ void gpgme_trust_item_unref (gpgme_trust_item_t item); -/* Release the trust item ITEM. Deprecated, use - gpgme_trust_item_unref. */ -void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED(0,4); - -/* Return the value of the attribute WHAT of ITEM, which has to be - representable by a string. Deprecated, use trust item structure - directly. */ -const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item, - _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - -/* Return the value of the attribute WHAT of KEY, which has to be - representable by an integer. IDX specifies a running index if the - attribute appears more than once in the key. Deprecated, use trust - item structure directly. */ -int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what, - const void *reserved, int idx) - _GPGME_DEPRECATED(0,4); - /* @@ -2209,35 +2029,14 @@ gpgme_error_t gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx, void *stat_cb_value, gpgme_error_t *op_err); -/* Compat. */ -struct _gpgme_op_assuan_result -{ - /* Deprecated. Use the second value in a DONE event or the - synchronous variant gpgme_op_assuan_transact_ext. */ - gpgme_error_t err _GPGME_DEPRECATED_OUTSIDE_GPGME(1,2); -}; -typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t; - - -/* Return the result of the last Assuan command. */ -gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx) - _GPGME_DEPRECATED(1,2); - -gpgme_error_t -gpgme_op_assuan_transact (gpgme_ctx_t ctx, - 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) _GPGME_DEPRECATED(1,2); - /* * Crypto container support. */ +/* An object to return results from a VFS mount operation. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ struct _gpgme_op_vfs_mount_result { char *mount_dir; @@ -2410,7 +2209,8 @@ void gpgme_conf_arg_release (gpgme_conf_arg_t arg, gpgme_conf_type_t type); /* Register a change for the value of OPT to ARG. If RESET is 1 (do not use any values but 0 or 1), ARG is ignored and the option is not changed (reverting a previous change). Otherwise, if ARG is - NULL, the option is cleared or reset to its default. */ + NULL, the option is cleared or reset to its default. The change + is done with gpgconf's --runtime option to immediately take effect. */ gpgme_error_t gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg); @@ -2425,7 +2225,9 @@ gpgme_error_t gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p); gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp); -/* Information about software versions. */ +/* Information about software versions. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ typedef struct _gpgme_op_query_swdb_result { /* RFU */ @@ -2552,8 +2354,323 @@ char *gpgme_addrspec_from_uid (const char *uid); /* - * Deprecated types. + * Deprecated types, constants and functions. */ + +/* The possible stati for gpgme_op_edit. The use of that function and + * these status codes are deprecated in favor of gpgme_op_interact. */ +typedef enum + { + GPGME_STATUS_EOF = 0, + /* mkstatus processing starts here */ + GPGME_STATUS_ENTER = 1, + GPGME_STATUS_LEAVE = 2, + GPGME_STATUS_ABORT = 3, + + GPGME_STATUS_GOODSIG = 4, + GPGME_STATUS_BADSIG = 5, + GPGME_STATUS_ERRSIG = 6, + + GPGME_STATUS_BADARMOR = 7, + + GPGME_STATUS_RSA_OR_IDEA = 8, /* (legacy) */ + GPGME_STATUS_KEYEXPIRED = 9, + GPGME_STATUS_KEYREVOKED = 10, + + GPGME_STATUS_TRUST_UNDEFINED = 11, + GPGME_STATUS_TRUST_NEVER = 12, + GPGME_STATUS_TRUST_MARGINAL = 13, + GPGME_STATUS_TRUST_FULLY = 14, + GPGME_STATUS_TRUST_ULTIMATE = 15, + + GPGME_STATUS_SHM_INFO = 16, /* (legacy) */ + GPGME_STATUS_SHM_GET = 17, /* (legacy) */ + GPGME_STATUS_SHM_GET_BOOL = 18, /* (legacy) */ + GPGME_STATUS_SHM_GET_HIDDEN = 19, /* (legacy) */ + + GPGME_STATUS_NEED_PASSPHRASE = 20, + GPGME_STATUS_VALIDSIG = 21, + GPGME_STATUS_SIG_ID = 22, + GPGME_STATUS_ENC_TO = 23, + GPGME_STATUS_NODATA = 24, + GPGME_STATUS_BAD_PASSPHRASE = 25, + GPGME_STATUS_NO_PUBKEY = 26, + GPGME_STATUS_NO_SECKEY = 27, + GPGME_STATUS_NEED_PASSPHRASE_SYM = 28, + GPGME_STATUS_DECRYPTION_FAILED = 29, + GPGME_STATUS_DECRYPTION_OKAY = 30, + GPGME_STATUS_MISSING_PASSPHRASE = 31, + GPGME_STATUS_GOOD_PASSPHRASE = 32, + GPGME_STATUS_GOODMDC = 33, + GPGME_STATUS_BADMDC = 34, + GPGME_STATUS_ERRMDC = 35, + GPGME_STATUS_IMPORTED = 36, + GPGME_STATUS_IMPORT_OK = 37, + GPGME_STATUS_IMPORT_PROBLEM = 38, + GPGME_STATUS_IMPORT_RES = 39, + GPGME_STATUS_FILE_START = 40, + GPGME_STATUS_FILE_DONE = 41, + GPGME_STATUS_FILE_ERROR = 42, + + GPGME_STATUS_BEGIN_DECRYPTION = 43, + GPGME_STATUS_END_DECRYPTION = 44, + GPGME_STATUS_BEGIN_ENCRYPTION = 45, + GPGME_STATUS_END_ENCRYPTION = 46, + + GPGME_STATUS_DELETE_PROBLEM = 47, + GPGME_STATUS_GET_BOOL = 48, + GPGME_STATUS_GET_LINE = 49, + GPGME_STATUS_GET_HIDDEN = 50, + GPGME_STATUS_GOT_IT = 51, + GPGME_STATUS_PROGRESS = 52, + GPGME_STATUS_SIG_CREATED = 53, + GPGME_STATUS_SESSION_KEY = 54, + GPGME_STATUS_NOTATION_NAME = 55, + GPGME_STATUS_NOTATION_DATA = 56, + GPGME_STATUS_POLICY_URL = 57, + GPGME_STATUS_BEGIN_STREAM = 58, /* (legacy) */ + GPGME_STATUS_END_STREAM = 59, /* (legacy) */ + GPGME_STATUS_KEY_CREATED = 60, + GPGME_STATUS_USERID_HINT = 61, + GPGME_STATUS_UNEXPECTED = 62, + GPGME_STATUS_INV_RECP = 63, + GPGME_STATUS_NO_RECP = 64, + GPGME_STATUS_ALREADY_SIGNED = 65, + GPGME_STATUS_SIGEXPIRED = 66, /* (legacy) */ + GPGME_STATUS_EXPSIG = 67, + GPGME_STATUS_EXPKEYSIG = 68, + GPGME_STATUS_TRUNCATED = 69, + GPGME_STATUS_ERROR = 70, + GPGME_STATUS_NEWSIG = 71, + GPGME_STATUS_REVKEYSIG = 72, + GPGME_STATUS_SIG_SUBPACKET = 73, + GPGME_STATUS_NEED_PASSPHRASE_PIN = 74, + GPGME_STATUS_SC_OP_FAILURE = 75, + GPGME_STATUS_SC_OP_SUCCESS = 76, + GPGME_STATUS_CARDCTRL = 77, + GPGME_STATUS_BACKUP_KEY_CREATED = 78, + GPGME_STATUS_PKA_TRUST_BAD = 79, + GPGME_STATUS_PKA_TRUST_GOOD = 80, + GPGME_STATUS_PLAINTEXT = 81, + GPGME_STATUS_INV_SGNR = 82, + GPGME_STATUS_NO_SGNR = 83, + GPGME_STATUS_SUCCESS = 84, + GPGME_STATUS_DECRYPTION_INFO = 85, + GPGME_STATUS_PLAINTEXT_LENGTH = 86, + GPGME_STATUS_MOUNTPOINT = 87, + GPGME_STATUS_PINENTRY_LAUNCHED = 88, + GPGME_STATUS_ATTRIBUTE = 89, + GPGME_STATUS_BEGIN_SIGNING = 90, + GPGME_STATUS_KEY_NOT_CREATED = 91, + GPGME_STATUS_INQUIRE_MAXLEN = 92, + GPGME_STATUS_FAILURE = 93, + GPGME_STATUS_KEY_CONSIDERED = 94, + GPGME_STATUS_TOFU_USER = 95, + GPGME_STATUS_TOFU_STATS = 96, + GPGME_STATUS_TOFU_STATS_LONG = 97, + GPGME_STATUS_NOTATION_FLAGS = 98 + } +gpgme_status_code_t; + +/* The callback type used by the deprecated functions gpgme_op_edit + * and gpgme_op_card_edit. */ +typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque, + gpgme_status_code_t status, + const char *args, int fd); + +gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out) _GPGME_DEPRECATED(1,7); +gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out) _GPGME_DEPRECATED(1,7); +gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out) + _GPGME_DEPRECATED(1,7); +gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key, + gpgme_edit_cb_t fnc, void *fnc_value, + gpgme_data_t out) + _GPGME_DEPRECATED(1,7); + +/* The possible signature stati. Deprecated, use error value in sig + status. */ +typedef enum + { + GPGME_SIG_STAT_NONE = 0, + GPGME_SIG_STAT_GOOD = 1, + GPGME_SIG_STAT_BAD = 2, + GPGME_SIG_STAT_NOKEY = 3, + GPGME_SIG_STAT_NOSIG = 4, + GPGME_SIG_STAT_ERROR = 5, + GPGME_SIG_STAT_DIFF = 6, + GPGME_SIG_STAT_GOOD_EXP = 7, + GPGME_SIG_STAT_GOOD_EXPKEY = 8 + } +_gpgme_sig_stat_t; +typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED(0,4); + +/* The available key and signature attributes. Deprecated, use the + individual result structures instead. */ +typedef enum + { + GPGME_ATTR_KEYID = 1, + GPGME_ATTR_FPR = 2, + GPGME_ATTR_ALGO = 3, + GPGME_ATTR_LEN = 4, + GPGME_ATTR_CREATED = 5, + GPGME_ATTR_EXPIRE = 6, + GPGME_ATTR_OTRUST = 7, + GPGME_ATTR_USERID = 8, + GPGME_ATTR_NAME = 9, + GPGME_ATTR_EMAIL = 10, + GPGME_ATTR_COMMENT = 11, + GPGME_ATTR_VALIDITY = 12, + GPGME_ATTR_LEVEL = 13, + GPGME_ATTR_TYPE = 14, + GPGME_ATTR_IS_SECRET = 15, + GPGME_ATTR_KEY_REVOKED = 16, + GPGME_ATTR_KEY_INVALID = 17, + GPGME_ATTR_UID_REVOKED = 18, + GPGME_ATTR_UID_INVALID = 19, + GPGME_ATTR_KEY_CAPS = 20, + GPGME_ATTR_CAN_ENCRYPT = 21, + GPGME_ATTR_CAN_SIGN = 22, + GPGME_ATTR_CAN_CERTIFY = 23, + GPGME_ATTR_KEY_EXPIRED = 24, + GPGME_ATTR_KEY_DISABLED = 25, + GPGME_ATTR_SERIAL = 26, + GPGME_ATTR_ISSUER = 27, + GPGME_ATTR_CHAINID = 28, + GPGME_ATTR_SIG_STATUS = 29, + GPGME_ATTR_ERRTOK = 30, + GPGME_ATTR_SIG_SUMMARY = 31, + GPGME_ATTR_SIG_CLASS = 32 + } +_gpgme_attr_t; +typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED(0,4); + +/* Retrieve the signature status of signature IDX in CTX after a + successful verify operation in R_STAT (if non-null). The creation + time stamp of the signature is returned in R_CREATED (if non-null). + The function returns a string containing the fingerprint. + Deprecated, use verify result directly. */ +const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx, + _gpgme_sig_stat_t *r_stat, + time_t *r_created) _GPGME_DEPRECATED(0,4); + +/* Retrieve certain attributes of a signature. IDX is the index + number of the signature after a successful verify operation. WHAT + is an attribute where GPGME_ATTR_EXPIRE is probably the most useful + one. WHATIDX is to be passed as 0 for most attributes . */ +unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx, + _gpgme_attr_t what, int whatidx) + _GPGME_DEPRECATED(0,4); +const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx, + _gpgme_attr_t what, int whatidx) + _GPGME_DEPRECATED(0,4); + + +/* Get the key used to create signature IDX in CTX and return it in + R_KEY. */ +gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key) + _GPGME_DEPRECATED(0,4); + +/* Create a new data buffer which retrieves the data from the callback + function READ_CB. Deprecated, please use gpgme_data_new_from_cbs + instead. */ +gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, + int (*read_cb) (void*,char *, + size_t,size_t*), + void *read_cb_value) + _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by a string. IDX specifies the sub key or user ID + for attributes related to sub keys or user IDs. Deprecated, use + key structure directly instead. */ +const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by an unsigned integer. IDX specifies the sub key or + user ID for attributes related to sub keys or user IDs. + Deprecated, use key structure directly instead. */ +unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of a signature on user ID + UID_IDX in KEY, which has to be representable by a string. IDX + specifies the signature. Deprecated, use key structure directly + instead. */ +const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of a signature on user ID + UID_IDX in KEY, which has to be representable by an unsigned + integer string. IDX specifies the signature. Deprecated, use key + structure directly instead. */ +unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + + +gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, + int *nr) _GPGME_DEPRECATED(0,4); + +/* Release the trust item ITEM. Deprecated, use + gpgme_trust_item_unref. */ +void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of ITEM, which has to be + representable by a string. Deprecated, use trust item structure + directly. */ +const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item, + _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + +/* Return the value of the attribute WHAT of KEY, which has to be + representable by an integer. IDX specifies a running index if the + attribute appears more than once in the key. Deprecated, use trust + item structure directly. */ +int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what, + const void *reserved, int idx) + _GPGME_DEPRECATED(0,4); + +/* Compat. + * This structure shall be considered read-only and an application + * must not allocate such a structure on its own. */ +struct _gpgme_op_assuan_result +{ + /* Deprecated. Use the second value in a DONE event or the + synchronous variant gpgme_op_assuan_transact_ext. */ + gpgme_error_t err _GPGME_DEPRECATED_OUTSIDE_GPGME(1,2); +}; +typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t; + + +/* Return the result of the last Assuan command. */ +gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx) + _GPGME_DEPRECATED(1,2); + +gpgme_error_t +gpgme_op_assuan_transact (gpgme_ctx_t ctx, + 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) _GPGME_DEPRECATED(1,2); + + + typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED(0,4); typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED(0,4); typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED(0,4); diff --git a/src/import.c b/src/import.c index 6233a15..4173fe9 100644 --- a/src/import.c +++ b/src/import.c @@ -193,7 +193,7 @@ parse_import_res (char *args, gpgme_import_result_t result) #define PARSE_NEXT(x) \ (x) = strtol (args, &tail, 0); \ - if (errno || args == tail || *tail != ' ') \ + if (errno || args == tail || !(*tail == ' ' || !*tail)) \ /* The crypto backend does not behave. */ \ return trace_gpg_error (GPG_ERR_INV_ENGINE); \ args = tail; @@ -249,7 +249,7 @@ import_status_handler (void *priv, gpgme_status_code_t code, char *args) default: break; } - return 0; + return err; } @@ -236,11 +236,13 @@ _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert) &uid->comment, dst); uid->address = _gpgme_mailbox_from_userid (uid->uid); - if (uid->address && uid->email && !strcmp (uid->address, uid->email)) + if ((!uid->email || !*uid->email) && uid->address && uid->name + && !strcmp (uid->name, uid->address)) { - /* The ADDRESS is the same as EMAIL: Save some space. */ - free (uid->address); - uid->address = uid->email; + /* Name and address are the same. This is a mailbox only key. + Use address as email and remove name. */ + *uid->name = '\0'; + uid->email = uid->address; } if (!key->uids) @@ -339,14 +341,10 @@ gpgme_key_unref (gpgme_key_t key) while (subkey) { gpgme_subkey_t next = subkey->next; - if (subkey->fpr) - free (subkey->fpr); - if (subkey->curve) - free (subkey->curve); - if (subkey->keygrip) - free (subkey->keygrip); - if (subkey->card_number) - free (subkey->card_number); + free (subkey->fpr); + free (subkey->curve); + free (subkey->keygrip); + free (subkey->card_number); free (subkey); subkey = next; } @@ -386,22 +384,15 @@ gpgme_key_unref (gpgme_key_t key) tofu = tofu_next; } - if (uid->address && uid->address != uid->email) - free (uid->address); - + free (uid->address); free (uid); uid = next_uid; } - if (key->issuer_serial) - free (key->issuer_serial); - if (key->issuer_name) - free (key->issuer_name); - - if (key->chain_id) - free (key->chain_id); - if (key->fpr) - free (key->fpr); + free (key->issuer_serial); + free (key->issuer_name); + free (key->chain_id); + free (key->fpr); free (key); } diff --git a/src/keylist.c b/src/keylist.c index 2ce0846..e16ba4d 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -416,6 +416,23 @@ parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field) } +/* Parse the compliance field. */ +static void +parse_pub_field18 (gpgme_subkey_t subkey, char *field) +{ + char *p, *endp; + unsigned long ul; + + for (p = field; p && (ul = strtoul (p, &endp, 10)) && p != endp; p = endp) + { + switch (ul) + { + case 23: subkey->is_de_vs = 1; break; + } + } +} + + /* Parse a tfs record. */ static gpg_error_t parse_tfs_record (gpgme_user_id_t uid, char **field, int nfield) @@ -535,7 +552,7 @@ keylist_colon_handler (void *priv, char *line) RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK } rectype = RT_NONE; -#define NR_FIELDS 17 +#define NR_FIELDS 20 char *field[NR_FIELDS]; int fields = 0; void *hook; @@ -712,6 +729,16 @@ keylist_colon_handler (void *priv, char *line) return gpg_error_from_syserror (); } + /* Field 18 has the compliance flags. */ + if (fields >= 17 && *field[17]) + parse_pub_field18 (subkey, field[17]); + + if (fields >= 20) + { + key->last_update = _gpgme_parse_timestamp_ul (field[18]); + key->origin = 0; /* Fixme: Not yet defined in gpg. */ + } + break; case RT_SUB: @@ -785,6 +812,10 @@ keylist_colon_handler (void *priv, char *line) return gpg_error_from_syserror (); } + /* Field 18 has the compliance flags. */ + if (fields >= 17 && *field[17]) + parse_pub_field18 (subkey, field[17]); + break; case RT_UID: @@ -793,12 +824,15 @@ keylist_colon_handler (void *priv, char *line) { if (_gpgme_key_append_name (key, field[9], 1)) return gpg_error (GPG_ERR_ENOMEM); /* FIXME */ - else - { - if (field[1]) - set_userid_flags (key, field[1]); - opd->tmp_uid = key->_last_uid; - } + + if (field[1]) + set_userid_flags (key, field[1]); + opd->tmp_uid = key->_last_uid; + if (fields >= 20) + { + opd->tmp_uid->last_update = _gpgme_parse_timestamp_ul (field[18]); + opd->tmp_uid->origin = 0; /* Fixme: Not yet defined in gpg. */ + } } break; @@ -1117,6 +1151,42 @@ gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[], } +/* Start a keylist operation within CTX to show keys contained + * in DATA. */ +gpgme_error_t +gpgme_op_keylist_from_data_start (gpgme_ctx_t ctx, gpgme_data_t data, + int reserved) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_from_data_start", ctx); + + if (!ctx || !data || reserved) + return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); + + err = _gpgme_op_reset (ctx, 2); + if (err) + return TRACE_ERR (err); + + err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return TRACE_ERR (err); + + _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx); + err = _gpgme_engine_set_colon_line_handler (ctx->engine, + keylist_colon_handler, ctx); + if (err) + return TRACE_ERR (err); + + err = _gpgme_engine_op_keylist_data (ctx->engine, data); + return TRACE_ERR (err); +} + + /* Return the next key from the keylist in R_KEY. */ gpgme_error_t gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key) diff --git a/src/libgpgme.vers b/src/libgpgme.vers index a55cd10..adc8d7d 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -126,6 +126,12 @@ GPGME_1.1 { gpgme_op_query_swdb; gpgme_op_query_swdb_result; + + gpgme_op_set_uid_flag_start; + gpgme_op_set_uid_flag; + + gpgme_op_decrypt_ext; + gpgme_op_decrypt_ext_start; }; @@ -223,6 +229,7 @@ GPGME_1.0 { gpgme_op_import_start; gpgme_op_keylist_end; gpgme_op_keylist_ext_start; + gpgme_op_keylist_from_data_start; gpgme_op_keylist_next; gpgme_op_keylist_result; gpgme_op_keylist_start; diff --git a/src/op-support.c b/src/op-support.c index d9217ec..817c569 100644 --- a/src/op-support.c +++ b/src/op-support.c @@ -94,6 +94,7 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type) _gpgme_release_result (ctx); LOCK (ctx->lock); ctx->canceled = 0; + ctx->redraw_suggested = 0; UNLOCK (ctx->lock); if (ctx->engine && no_reset) @@ -89,6 +89,9 @@ gpgme_error_t _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx); 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. */ diff --git a/src/posix-io.c b/src/posix-io.c index 5296f5f..a351806 100644 --- a/src/posix-io.c +++ b/src/posix-io.c @@ -287,37 +287,43 @@ get_max_fds (void) int rc; /* Under Linux we can figure out the highest used file descriptor by - * reading /proc/self/fd. This is in the common cases much fast than - * for example doing 4096 close calls where almost all of them will - * fail. */ -#ifdef __linux__ - { - DIR *dir = NULL; - struct dirent *dir_entry; - const char *s; - int x; - - dir = opendir ("/proc/self/fd"); - if (dir) - { - while ((dir_entry = readdir (dir))) - { - s = dir_entry->d_name; - if ( *s < '0' || *s > '9') - continue; - x = atoi (s); - if (x > fds) - fds = x; - } - closedir (dir); - } - if (fds != -1) - { - fds++; - source = "/proc"; - } - } -#endif /* __linux__ */ + * reading /proc/self/fd. This is in the common cases much faster + * than for example doing 4096 close calls where almost all of them + * will fail. + * + * Unfortunately we can't call opendir between fork and exec in a + * multi-threaded process because opendir uses malloc and thus a + * mutex which may deadlock with a malloc in another thread. Thus + * the code is not used until we can have a opendir variant which + * does not use malloc. */ +/* #ifdef __linux__ */ +/* { */ +/* DIR *dir = NULL; */ +/* struct dirent *dir_entry; */ +/* const char *s; */ +/* int x; */ + +/* dir = opendir ("/proc/self/fd"); */ +/* if (dir) */ +/* { */ +/* while ((dir_entry = readdir (dir))) */ +/* { */ +/* s = dir_entry->d_name; */ +/* if ( *s < '0' || *s > '9') */ +/* continue; */ +/* x = atoi (s); */ +/* if (x > fds) */ +/* fds = x; */ +/* } */ +/* closedir (dir); */ +/* } */ +/* if (fds != -1) */ +/* { */ +/* fds++; */ +/* source = "/proc"; */ +/* } */ +/* } */ +/* #endif /\* __linux__ *\/ */ #ifdef RLIMIT_NOFILE if (fds == -1) @@ -453,10 +459,9 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, /* Intermediate child to prevent zombie processes. */ if ((pid = fork ()) == 0) { - int max_fds = get_max_fds (); - int fd; - /* Child. */ + int max_fds = -1; + int fd; int seen_stdin = 0; int seen_stdout = 0; int seen_stderr = 0; @@ -464,15 +469,40 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, if (atfork) atfork (atforkvalue, 0); - /* First close all fds which will not be inherited. */ - for (fd = 0; fd < max_fds; fd++) - { - for (i = 0; fd_list[i].fd != -1; i++) - if (fd_list[i].fd == fd) - break; - if (fd_list[i].fd == -1) - close (fd); - } + /* First close all fds which will not be inherited. If we + * have closefrom(2) we first figure out the highest fd we + * do not want to close, then call closefrom, and on success + * use the regular code to close all fds up to the start + * point of closefrom. Note that Solaris' closefrom does + * not return errors. */ +#ifdef HAVE_CLOSEFROM + { + fd = -1; + for (i = 0; fd_list[i].fd != -1; i++) + if (fd_list[i].fd > fd) + fd = fd_list[i].fd; + fd++; +#ifdef __sun + closefrom (fd); + max_fds = fd; +#else /*!__sun */ + while ((i = closefrom (fd)) && errno == EINTR) + ; + if (!i || errno == EBADF) + max_fds = fd; +#endif /*!__sun*/ + } +#endif /*HAVE_CLOSEFROM*/ + if (max_fds == -1) + max_fds = get_max_fds (); + for (fd = 0; fd < max_fds; fd++) + { + for (i = 0; fd_list[i].fd != -1; i++) + if (fd_list[i].fd == fd) + break; + if (fd_list[i].fd == -1) + close (fd); + } /* And now dup and close those to be duplicated. */ for (i = 0; fd_list[i].fd != -1; i++) diff --git a/src/progress.c b/src/progress.c index c10ccaa..066a7f5 100644 --- a/src/progress.c +++ b/src/progress.c @@ -31,6 +31,8 @@ #include "debug.h" +/* The status handler for progress status lines which also monitors + * the PINENTRY_LAUNCHED status. */ gpgme_error_t _gpgme_progress_status_handler (void *priv, gpgme_status_code_t code, char *args) @@ -42,6 +44,12 @@ _gpgme_progress_status_handler (void *priv, gpgme_status_code_t code, int current = 0; int total = 0; + if (code == GPGME_STATUS_PINENTRY_LAUNCHED) + { + ctx->redraw_suggested = 1; + return 0; + } + if (code != GPGME_STATUS_PROGRESS || !*args || !ctx->progress_cb) return 0; @@ -95,11 +95,12 @@ _gpgme_stpcpy (char *a, const char *b) #define stpcpy(a,b) _gpgme_stpcpy ((a), (b)) #endif /*!HAVE_STPCPY*/ -#if !HAVE_VASPRINTF -#include <stdarg.h> -int vasprintf (char **result, const char *format, va_list args); -int asprintf (char **result, const char *format, ...); -#endif + +/* Due to a bug in mingw32's snprintf related to the 'l' modifier and + for increased portability we use our snprintf on all systems. */ +#undef snprintf +#define snprintf gpgrt_snprintf + #if REPLACE_TTYNAME_R int _gpgme_ttyname_r (int fd, char *buf, size_t buflen); @@ -164,6 +165,9 @@ gpgme_off_t _gpgme_string_to_off (const char *string); point to the next non-parsed character in TIMESTRING. */ time_t _gpgme_parse_timestamp (const char *timestamp, char **endp); +/* Variant of _gpgme_parse_timestamp to return an unsigned long or 0 + * on error or missing timestamp. */ +unsigned long _gpgme_parse_timestamp_ul (const char *timestamp); gpgme_error_t _gpgme_map_gnupg_error (char *err); diff --git a/src/vasprintf.c b/src/vasprintf.c deleted file mode 100644 index 4c40131..0000000 --- a/src/vasprintf.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Like vsprintf but provides a pointer to malloc'd storage, which must - be freed by the caller. - Copyright (C) 1994, 2002 Free Software Foundation, Inc. - -This file is part of the libiberty library. -Libiberty is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -Libiberty 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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with libiberty; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdarg.h> - - -#ifndef va_copy /* According to POSIX, va_copy is a macro. */ -#if defined (__GNUC__) && defined (__PPC__) \ - && (defined (_CALL_SYSV) || defined (_WIN32)) -#define va_copy(d, s) (*(d) = *(s)) -#elif defined (MUST_COPY_VA_BYVAL) -#define va_copy(d, s) ((d) = (s)) -#else -#define va_copy(d, s) memcpy ((d), (s), sizeof (va_list)) -#endif -#endif - - -#ifdef TEST -int global_total_width; -#endif - -static int int_vasprintf (char **, const char *, va_list *); - -static int -int_vasprintf (result, format, args) - char **result; - const char *format; - va_list *args; -{ -#ifdef HAVE_W32CE_SYSTEM - /* No va_copy and the replacement above doesn't work. */ -#define MAX_STRLEN 256 - *result = malloc (MAX_STRLEN); - if (*result != NULL) - { - int res = _vsnprintf (*result, MAX_STRLEN, format, *args); - (*result)[MAX_STRLEN - 1] = '\0'; - return res; - } - else - return 0; -#else - const char *p = format; - /* Add one to make sure that it is never zero, which might cause malloc - to return NULL. */ - int total_width = strlen (format) + 1; - va_list ap; - - va_copy (ap, *args); - - while (*p != '\0') - { - if (*p++ == '%') - { - while (strchr ("-+ #0", *p)) - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - total_width += strtoul (p, (char **) &p, 10); - if (*p == '.') - { - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - total_width += strtoul (p, (char **) &p, 10); - } - while (strchr ("hlL", *p)) - ++p; - /* Should be big enough for any format specifier except %s and floats. */ - total_width += 30; - switch (*p) - { - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - case 'c': - (void) va_arg (ap, int); - break; - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - (void) va_arg (ap, double); - /* Since an ieee double can have an exponent of 307, we'll - make the buffer wide enough to cover the gross case. */ - total_width += 307; - break; - case 's': - { - char *tmp = va_arg (ap, char *); - if (tmp) - total_width += strlen (tmp); - else /* in case the vsprintf does prints a text */ - total_width += 25; /* e.g. "(null pointer reference)" */ - } - break; - case 'p': - case 'n': - (void) va_arg (ap, char *); - break; - } - p++; - } - } -#ifdef TEST - global_total_width = total_width; -#endif - *result = malloc (total_width); - if (*result != NULL) - return vsprintf (*result, format, *args); - else - return 0; -#endif -} - -int -vasprintf (result, format, args) - char **result; - const char *format; -#if defined (_BSD_VA_LIST_) && defined (__FreeBSD__) - _BSD_VA_LIST_ args; -#else - va_list args; -#endif -{ - return int_vasprintf (result, format, &args); -} - - -int -asprintf (char **buf, const char *fmt, ...) -{ - int status; - va_list ap; - - va_start (ap, fmt); - status = vasprintf (buf, fmt, ap); - va_end (ap); - return status; -} - - -#ifdef TEST -void -checkit (const char* format, ...) -{ - va_list args; - char *result; - - va_start (args, format); - vasprintf (&result, format, args); - if (strlen (result) < global_total_width) - printf ("PASS: "); - else - printf ("FAIL: "); - printf ("%d %s\n", global_total_width, result); -} - -int -main (void) -{ - checkit ("%d", 0x12345678); - checkit ("%200d", 5); - checkit ("%.300d", 6); - checkit ("%100.150d", 7); - checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\ -777777777777777777333333333333366666666666622222222222777777777777733333"); - checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"); -} -#endif /* TEST */ diff --git a/src/verify.c b/src/verify.c index faa8deb..900f925 100644 --- a/src/verify.c +++ b/src/verify.c @@ -46,6 +46,7 @@ typedef struct int did_prepare_new_sig; int only_newsig_seen; int plaintext_seen; + int conflict_user_seen; } *op_data_t; @@ -680,6 +681,14 @@ parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol) goto leave; } + if (sig->key && sig->key->fpr && strcmp (sig->key->fpr, fpr)) + { + /* GnuPG since 2.1.17 emits multiple TOFU_USER lines with + different fingerprints in case of conflicts for a signature. */ + err = gpg_error (GPG_ERR_DUP_VALUE); + goto leave; + } + args = tail; tail = strchr (args, ' '); if (tail == args) @@ -708,12 +717,6 @@ parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol) err = trace_gpg_error (GPG_ERR_INTERNAL); goto leave; } - else if (strcmp (sig->key->fpr, fpr)) - { - /* The engine did not emit NEWSIG before a new key. */ - err = trace_gpg_error (GPG_ERR_INV_ENGINE); - goto leave; - } err = _gpgme_key_append_name (sig->key, address, 0); if (err) @@ -930,6 +933,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) calc_sig_summary (sig); err = prepare_new_sig (opd); opd->only_newsig_seen = 1; + opd->conflict_user_seen = 0; return err; case GPGME_STATUS_GOODSIG: @@ -995,16 +999,35 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_TOFU_USER: opd->only_newsig_seen = 0; - return sig ? parse_tofu_user (sig, args, ctx->protocol) - /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE); + if (!sig) + return trace_gpg_error (GPG_ERR_INV_ENGINE); + err = parse_tofu_user (sig, args, ctx->protocol); + /* gpg emits TOFU User lines for each conflicting key. + * GPGME does not expose this to have a clean API and + * a GPGME user can do a keylisting with the address + * normalisation. + * So when a duplicated TOFU_USER line is encountered + * we ignore the conflicting tofu stats emited afterwards. + */ + if (gpg_err_code (err) == GPG_ERR_DUP_VALUE) + { + opd->conflict_user_seen = 1; + break; + } + opd->conflict_user_seen = 0; + return trace_gpg_error (err); case GPGME_STATUS_TOFU_STATS: opd->only_newsig_seen = 0; + if (opd->conflict_user_seen) + break; return sig ? parse_tofu_stats (sig, args) /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE); case GPGME_STATUS_TOFU_STATS_LONG: opd->only_newsig_seen = 0; + if (opd->conflict_user_seen) + break; return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description) /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE); diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in index 3ce38f0..2b1cc81 100644 --- a/src/versioninfo.rc.in +++ b/src/versioninfo.rc.in @@ -39,7 +39,7 @@ BEGIN VALUE "FileDescription", "GPGME - GnuPG Made Easy\0" VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0" VALUE "InternalName", "gpgme\0" - VALUE "LegalCopyright", "Copyright © 2001-2016 g10 Code GmbH\0" + VALUE "LegalCopyright", "Copyright © 2001-2017 g10 Code GmbH\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "gpgme.dll\0" VALUE "PrivateBuild", "\0" diff --git a/src/vfs-create.c b/src/vfs-create.c index a01d4da..a3bec19 100644 --- a/src/vfs-create.c +++ b/src/vfs-create.c @@ -138,7 +138,7 @@ _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); } - if (asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0) + if (gpgrt_asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0) { err = gpg_error_from_syserror (); free (container_file_esc); @@ -147,7 +147,7 @@ _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL, op_err); - free (cmd); + gpgrt_free (cmd); if (err || *op_err) { free (container_file_esc); @@ -156,7 +156,7 @@ _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], recp++; } - if (asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0) + if (gpgrt_asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0) { err = gpg_error_from_syserror (); free (container_file_esc); @@ -166,7 +166,7 @@ _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL, op_err); - free (cmd); + gpgrt_free (cmd); return err; } diff --git a/src/vfs-mount.c b/src/vfs-mount.c index 5d2f2a9..68a8efe 100644 --- a/src/vfs-mount.c +++ b/src/vfs-mount.c @@ -184,7 +184,7 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, if (err) return err; - if (asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0) + if (gpgrt_asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0) { err = gpg_error_from_syserror (); free (container_file_esc); @@ -194,7 +194,7 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, NULL, NULL, op_err); - free (cmd); + gpgrt_free (cmd); if (err || *op_err) return err; @@ -206,7 +206,7 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, if (err) return err; - if (asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0) + if (gpgrt_asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0) { err = gpg_error_from_syserror (); free (mount_dir_esc); @@ -216,13 +216,13 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, } else { - if (asprintf (&cmd, "MOUNT") < 0) + if (gpgrt_asprintf (&cmd, "MOUNT") < 0) return gpg_error_from_syserror (); } err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, _gpgme_vfs_mount_status_handler, ctx, op_err); - free (cmd); + gpgrt_free (cmd); return err; } diff --git a/src/w32-io.c b/src/w32-io.c index 0d1c810..eed8a00 100644 --- a/src/w32-io.c +++ b/src/w32-io.c @@ -700,7 +700,7 @@ writer (void *arg) for (;;) { LOCK (ctx->mutex); - if (ctx->stop_me) + if (ctx->stop_me && !ctx->nbytes) { UNLOCK (ctx->mutex); break; @@ -717,7 +717,7 @@ writer (void *arg) TRACE_LOG ("got data to send"); LOCK (ctx->mutex); } - if (ctx->stop_me) + if (ctx->stop_me && !ctx->nbytes) { UNLOCK (ctx->mutex); break; @@ -776,6 +776,9 @@ writer (void *arg) TRACE_LOG ("waiting for close"); WaitForSingleObject (ctx->close_ev, INFINITE); + if (ctx->nbytes) + TRACE_LOG1 ("still %d bytes in buffer at close time", ctx->nbytes); + CloseHandle (ctx->close_ev); CloseHandle (ctx->have_data); CloseHandle (ctx->is_empty); @@ -892,6 +895,9 @@ destroy_writer (struct writer_context_s *ctx) SetEvent (ctx->have_data); UNLOCK (ctx->mutex); + /* Give the writer a chance to flush the buffer. */ + WaitForSingleObject (ctx->is_empty, INFINITE); + #ifdef HAVE_W32CE_SYSTEM /* Scenario: We never create a full pipe, but already started writing more than the pipe buffer. Then we need to unblock the @@ -1637,11 +1643,11 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, "with your installation.\n" "Please report the problem to your " "distributor of GpgME.\n\n" - "Developers Note: The install dir can be " + "Developer's Note: The install dir can be " "manually set with: gpgme_set_global_flag", _gpgme_get_inst_dir ()); MessageBoxA (NULL, msg, "GpgME not installed correctly", MB_OK); - free (msg); + gpgrt_free (msg); gpg_err_set_errno (EIO); return TRACE_SYSRES (-1); } diff --git a/src/w32-util.c b/src/w32-util.c index ad36c9a..5b02c7e 100644 --- a/src/w32-util.c +++ b/src/w32-util.c @@ -577,9 +577,10 @@ _gpgme_get_gpgconf_path (void) "Install Directory"); if (tmp) { - if (gpgrt_asprintf (&dir, "%s\\bin", tmp) == -1) - return NULL; + dir = _gpgme_strconcat (tmp, "\\bin", NULL); free (tmp); + if (!dir) + return NULL; } } if (dir) |