From f7700a016926f0d8e9cb3c0337837deb7fe01079 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Apr 2018 09:17:27 +0200 Subject: core: Add new context flag "no-symkey-cache". * src/gpgme.c (gpgme_set_ctx_flag): Set flag. (gpgme_get_ctx_flag): Get flag. * src/context.h (struct gpgme_context): Add field no_symkey_cache. * src/engine-gpg.c (struct engine_gpg): Ditto. (gpg_set_engine_flags): Set flag. (build_argv): Pass option --no-symkey-cache to gpg. * tests/run-decrypt.c (print_result): Fix segv for symmetric messages. (main): New option --no-symkey-cache. * tests/run-encrypt.c (main): New option --no-symkey-cache. Signed-off-by: Werner Koch --- src/engine-gpg.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 3b9a6ff5..a37d1f7b 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -145,6 +145,10 @@ struct engine_gpg gpgme_pinentry_mode_t pinentry_mode; char request_origin[10]; + struct { + unsigned int no_symkey_cache : 1; + } flags; + /* NULL or the data object fed to --override_session_key-fd. */ gpgme_data_t override_session_key; }; @@ -642,6 +646,10 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx) else strcpy (gpg->request_origin, ctx->request_origin); } + else if (ctx->no_symkey_cache && have_gpg_version (gpg, "2.2.7")) + { + gpg->flags.no_symkey_cache = 1; + } else *gpg->request_origin = 0; } @@ -875,7 +883,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; if (!gpg->cmd.used) argc++; /* --batch */ - argc += 2; /* --no-sk-comments, --request-origin */ + argc += 3; /* --no-sk-comments, --request-origin, --no-symkey-cache */ argv = calloc (argc + 1, sizeof *argv); if (!argv) @@ -937,6 +945,19 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; } + if (gpg->flags.no_symkey_cache) + { + argv[argc] = strdup ("--no-symkey-cache"); + if (!argv[argc]) + { + int saved_err = gpg_error_from_syserror (); + free (fd_data_map); + free_argv (argv); + return saved_err; + } + argc++; + } + if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0")) { const char *s = NULL; -- cgit v1.2.3 From a1f76b3b54b75a150fe272b804d85ffd40a507a6 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 08:33:44 +0200 Subject: core: Add extended versions of the encrypt functions. * src/gpgme.h.in (gpgme_op_encrypt_ext_start) New. (gpgme_op_encrypt_ext): New. (gpgme_op_encrypt_sign_ext_start): New. (gpgme_op_encrypt_sign_ext): New. * src/libgpgme.vers, tests/run-encrypt.c: Add them. * src/encrypt.c (encrypt_start): Add arg recpstring. (gpgme_op_encrypt): Factor code out to ... (gpgme_op_encrypt_ext): new function with new arg recpstring. (gpgme_op_encrypt_start): Factor code out to ... (gpgme_op_encrypt_ext_start): new function with new arg recpstring. * src/encrypt-sign.c (encrypt_sign_start): Add arg recpstring. (gpgme_op_encrypt_sign): Factor code out to ... (gpgme_op_encrypt_sign_ext): new function with new arg recpstring. (gpgme_op_encrypt_sign_start): Factor code out to ... (gpgme_op_encrypt_sign_ext_start): new function with new arg recpstring. * src/engine-backend.h (struct engine_ops): Change fields encrypt and encrypt_sign. * src/engine.c (_gpgme_engine_op_encrypt): Add arg recpstring and pass to engine. (_gpgme_engine_op_encrypt_sign): Ditto. * src/engine-gpg.c (append_args_from_recipients_string): New. (gpg_encrypt): Add arg recpstring and call new function as needed. (gpg_encrypt_sign): Ditto. * src/engine-gpgsm.c (set_recipients_from_string): New. (gpgsm_encrypt): Add arg recpstring and call new function as needed. * src/engine-uiserver.c (set_recipients_from_string): New. (uiserver_encrypt): Add arg recpstring and call new function as needed. * tests/run-encrypt.c (xstrdup): New. (main): Add option --keystring. * src/gpgme-json.c (get_keys): Simplify. (op_encrypt): Modify to make use of the extended encrypt function. -- This new feature can be used to avoid the need for a key lookup and thus several extra calls to the backend. Note that run-test uses a semicolon as delimiter because that make testing the feature on the command line much easier. Signed-off-by: Werner Koch --- src/engine-gpg.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 9 deletions(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index a37d1f7b..809806c4 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1914,17 +1914,64 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) } +/* Take recipients from the LF delimited STRING and add -r args. */ +static gpg_error_t +append_args_from_recipients_string (engine_gpg_t gpg, const char *string) +{ + gpg_error_t err = 0; + int any = 0; + const char *s; + int n; + + do + { + /* Skip leading white space */ + while (*string == ' ' || *string == '\t') + string++; + if (!*string) + break; + + /* Look for the LF. */ + s = strchr (string, '\n'); + if (s) + n = s - string; + else + n = strlen (string); + while (n && (string[n-1] == ' ' || string[n-1] == '\t')) + n--; + + /* Add arg if it is not empty. */ + if (n) + { + err = add_arg (gpg, "-r"); + if (!err) + err = add_arg_len (gpg, NULL, string, n); + if (!err) + any = 1; + } + + string += n + !!s; + } + while (!err); + + if (!err && !any) + err = gpg_error (GPG_ERR_MISSING_KEY); + return err; +} + + static gpgme_error_t -gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, +gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, + gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor) { engine_gpg_t gpg = engine; gpgme_error_t err = 0; - if (recp) + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); - if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) + if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring))) err = add_arg (gpg, "--symmetric"); if (!err && use_armor) @@ -1951,7 +1998,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); - if (recp) + if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ @@ -1961,7 +2008,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) err = add_arg (gpg, "--no-encrypt-to"); - if (!err) + if (!err && !recp && recpstring) + err = append_args_from_recipients_string (gpg, recpstring); + else if (!err) err = append_args_from_recipients (gpg, recp); } @@ -1995,6 +2044,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, static gpgme_error_t gpg_encrypt_sign (void *engine, gpgme_key_t recp[], + const char *recpstring, gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t ciph, int use_armor, gpgme_ctx_t ctx /* FIXME */) @@ -2002,10 +2052,10 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], engine_gpg_t gpg = engine; gpgme_error_t err = 0; - if (recp) + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); - if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp)) + if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || (!recp && !recpstring))) err = add_arg (gpg, "--symmetric"); if (!err) @@ -2023,7 +2073,7 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], && have_gpg_version (gpg, "2.1.14")) err = add_arg (gpg, "--mimemode"); - if (recp) + if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ @@ -2033,7 +2083,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) err = add_arg (gpg, "--no-encrypt-to"); - if (!err) + if (!err && !recp && recpstring) + err = append_args_from_recipients_string (gpg, recpstring); + else if (!err) err = append_args_from_recipients (gpg, recp); } -- cgit v1.2.3 From 86efba2be270d2cdd0bc66c9d3fe190495b7af2f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 09:40:27 +0200 Subject: core: New encryption flag GPGME_ENCRYPT_WANT_ADDRESS. * src/gpgme.h.in (GPGME_ENCRYPT_WANT_ADDRESS): New flag. * src/engine-gpg.c (add_arg_recipient): New. (add_arg_recipient_string): New. (append_args_from_recipients): Call new helper function. (append_args_from_recipients_string): Ditto. * src/gpgme-json.c (op_encrypt): Add flag "want-address". -- Signed-off-by: Werner Koch --- src/engine-gpg.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 8 deletions(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 809806c4..90e3b89e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -43,6 +43,7 @@ #include "sema.h" #include "debug.h" #include "data.h" +#include "mbox-util.h" #include "engine-backend.h" @@ -1892,8 +1893,70 @@ gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out, } +/* Add a single argument from a key to an -r option. */ +static gpg_error_t +add_arg_recipient (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + gpgme_key_t key) +{ + gpg_error_t err; + + if ((flags & GPGME_ENCRYPT_WANT_ADDRESS)) + { + /* We have no way to figure out which mail address was + * requested. FIXME: It would be possible to figure this out by + * consulting the SENDER property of the context. */ + err = gpg_error (GPG_ERR_INV_USER_ID); + } + else + err = add_arg (gpg, key->subkeys->fpr); + + return err; +} + + +/* Add a single argument from a USERID string to an -r option. */ +static gpg_error_t +add_arg_recipient_string (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + const char *userid, int useridlen) +{ + gpg_error_t err; + + if ((flags & GPGME_ENCRYPT_WANT_ADDRESS)) + { + char *tmpstr, *mbox; + + tmpstr = malloc (useridlen + 1); + if (!tmpstr) + err = gpg_error_from_syserror (); + else + { + memcpy (tmpstr, userid, useridlen); + tmpstr[useridlen] = 0; + + mbox = _gpgme_mailbox_from_userid (tmpstr); + if (!mbox) + { + err = gpg_error_from_syserror (); + if (gpg_err_code (err) == GPG_ERR_EINVAL) + err = gpg_error (GPG_ERR_INV_USER_ID); + } + else + err = add_arg (gpg, mbox); + + free (mbox); + free (tmpstr); + } + } + else + err = add_arg_len (gpg, NULL, userid, useridlen); + + return err; +} + + static gpgme_error_t -append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) +append_args_from_recipients (engine_gpg_t gpg, gpgme_encrypt_flags_t flags, + gpgme_key_t recp[]) { gpgme_error_t err = 0; int i = 0; @@ -1905,7 +1968,7 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) if (!err) err = add_arg (gpg, "-r"); if (!err) - err = add_arg (gpg, recp[i]->subkeys->fpr); + err = add_arg_recipient (gpg, flags, recp[i]); if (err) break; i++; @@ -1916,7 +1979,9 @@ append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[]) /* Take recipients from the LF delimited STRING and add -r args. */ static gpg_error_t -append_args_from_recipients_string (engine_gpg_t gpg, const char *string) +append_args_from_recipients_string (engine_gpg_t gpg, + gpgme_encrypt_flags_t flags, + const char *string) { gpg_error_t err = 0; int any = 0; @@ -1945,7 +2010,7 @@ append_args_from_recipients_string (engine_gpg_t gpg, const char *string) { err = add_arg (gpg, "-r"); if (!err) - err = add_arg_len (gpg, NULL, string, n); + err = add_arg_recipient_string (gpg, flags, string, n); if (!err) any = 1; } @@ -2009,9 +2074,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, err = add_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) - err = append_args_from_recipients_string (gpg, recpstring); + err = append_args_from_recipients_string (gpg, flags, recpstring); else if (!err) - err = append_args_from_recipients (gpg, recp); + err = append_args_from_recipients (gpg, flags, recp); } /* Tell the gpg object about the data. */ @@ -2084,9 +2149,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], err = add_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) - err = append_args_from_recipients_string (gpg, recpstring); + err = append_args_from_recipients_string (gpg, flags, recpstring); else if (!err) - err = append_args_from_recipients (gpg, recp); + err = append_args_from_recipients (gpg, flags, recp); } if (!err) -- cgit v1.2.3 From 4bba3b8e2c350b8ff0d562ec63cc03a096448d84 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 10:04:20 +0200 Subject: core: Allow for --hidden keyword in OpenPGP recpstrings. * src/engine-gpg.c (append_args_from_recipients_string): Add special keywords. -- GnuPG-bug-id: 3775 Signed-off-by: Werner Koch --- src/engine-gpg.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 90e3b89e..49a1c75e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1985,6 +1985,8 @@ append_args_from_recipients_string (engine_gpg_t gpg, { gpg_error_t err = 0; int any = 0; + int ignore = 0; + int hidden = 0; const char *s; int n; @@ -2005,10 +2007,14 @@ append_args_from_recipients_string (engine_gpg_t gpg, while (n && (string[n-1] == ' ' || string[n-1] == '\t')) n--; - /* Add arg if it is not empty. */ - if (n) + if (!ignore && n == 2 && !memcmp (string, "--", 2)) + ignore = 1; + else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8)) + hidden = 1; + else if (n) { - err = add_arg (gpg, "-r"); + /* Add arg if it is not empty. */ + err = add_arg (gpg, hidden? "-R":"-r"); if (!err) err = add_arg_recipient_string (gpg, flags, string, n); if (!err) -- cgit v1.2.3 From c143ab692c7fc7cf2ec0aebe40b9479ee15eaba9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 11:06:27 +0200 Subject: core: For OpenPGP let offline mode disable dirmngr. * src/engine-gpg.c (struct engine_gpg): New flag.offline. (gpg_set_engine_flags): Set it. Also fix setting of no_symkey_cache. (build_argv): Pass --disable-dirmngr in offline mode. -- GnuPG-bug-id: 3831 Signed-off-by: Werner Koch --- src/engine-gpg.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 49a1c75e..fdb786a9 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -148,6 +148,7 @@ struct engine_gpg struct { unsigned int no_symkey_cache : 1; + unsigned int offline : 1; } flags; /* NULL or the data object fed to --override_session_key-fd. */ @@ -647,12 +648,14 @@ gpg_set_engine_flags (void *engine, const gpgme_ctx_t ctx) else strcpy (gpg->request_origin, ctx->request_origin); } - else if (ctx->no_symkey_cache && have_gpg_version (gpg, "2.2.7")) - { - gpg->flags.no_symkey_cache = 1; - } else *gpg->request_origin = 0; + + gpg->flags.no_symkey_cache = (ctx->no_symkey_cache + && have_gpg_version (gpg, "2.2.7")); + + gpg->flags.offline = (ctx->offline && have_gpg_version (gpg, "2.1.23")); + } @@ -884,7 +887,8 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; if (!gpg->cmd.used) argc++; /* --batch */ - argc += 3; /* --no-sk-comments, --request-origin, --no-symkey-cache */ + argc += 4; /* --no-sk-comments, --request-origin, --no-symkey-cache */ + /* --disable-dirmngr */ argv = calloc (argc + 1, sizeof *argv); if (!argv) @@ -959,6 +963,19 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; } + if (gpg->flags.offline) + { + argv[argc] = strdup ("--disable-dirmngr"); + if (!argv[argc]) + { + int saved_err = gpg_error_from_syserror (); + free (fd_data_map); + free_argv (argv); + return saved_err; + } + argc++; + } + if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0")) { const char *s = NULL; -- cgit v1.2.3 From 3589da0500f1c80717e658d103a0cb2751d27b49 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 17 Apr 2018 12:40:30 +0200 Subject: core: New keyword --file for OpenPGP recpstring. * src/engine-gpg.c (append_args_from_recipients_string): Add new flags. -- Now you can use gpgme to encrypt without first importing a key. Signed-off-by: Werner Koch --- src/engine-gpg.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/engine-gpg.c') diff --git a/src/engine-gpg.c b/src/engine-gpg.c index fdb786a9..173e940c 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2001,9 +2001,11 @@ append_args_from_recipients_string (engine_gpg_t gpg, const char *string) { gpg_error_t err = 0; + gpgme_encrypt_flags_t orig_flags = flags; int any = 0; int ignore = 0; int hidden = 0; + int file = 0; const char *s; int n; @@ -2028,10 +2030,22 @@ append_args_from_recipients_string (engine_gpg_t gpg, ignore = 1; else if (!ignore && n == 8 && !memcmp (string, "--hidden", 8)) hidden = 1; - else if (n) + else if (!ignore && n == 11 && !memcmp (string, "--no-hidden", 11)) + hidden = 0; + else if (!ignore && n == 6 && !memcmp (string, "--file", 6)) { - /* Add arg if it is not empty. */ - err = add_arg (gpg, hidden? "-R":"-r"); + file = 1; + /* Because the key is used as is we need to ignore this flag: */ + flags &= ~GPGME_ENCRYPT_WANT_ADDRESS; + } + else if (!ignore && n == 9 && !memcmp (string, "--no-file", 9)) + { + file = 0; + flags = orig_flags; + } + else if (n) /* Not empty - use it. */ + { + err = add_arg (gpg, file? (hidden? "-F":"-f") : (hidden? "-R":"-r")); if (!err) err = add_arg_recipient_string (gpg, flags, string, n); if (!err) -- cgit v1.2.3