diff options
Diffstat (limited to 'src/engine-gpg.c')
-rw-r--r-- | src/engine-gpg.c | 748 |
1 files changed, 493 insertions, 255 deletions
diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 9d20f2ba..41f24d1e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -57,6 +57,7 @@ struct arg_and_data_s int inbound; /* True if this is used for reading from gpg. */ int dup_to; int print_fd; /* Print the fd number and not the special form of it. */ + int gpg_arg; /* True if this argument is not known by gpgtar. */ int *arg_locp; /* Write back the argv idx of this argument when building command line to this location. */ char arg[FLEXIBLE_ARRAY_MEMBER]; /* Used if data above is not used. */ @@ -145,6 +146,7 @@ struct engine_gpg char *trust_model; struct { + unsigned int use_gpgtar : 1; unsigned int no_symkey_cache : 1; unsigned int offline : 1; unsigned int ignore_mdc_error : 1; @@ -222,11 +224,32 @@ close_notify_handler (int fd, void *opaque) } } +static void +_append_to_arglist (engine_gpg_t gpg, struct arg_and_data_s *a) +{ + a->next = NULL; + *gpg->argtail = a; + gpg->argtail = &a->next; +} + +static void +_prepend_to_arglist (engine_gpg_t gpg, struct arg_and_data_s *a) +{ + a->next = gpg->arglist; + if (!gpg->arglist) + { + /* If this is the first argument, we need to update the tail + pointer. */ + gpg->argtail = &a->next; + } + gpg->arglist = a; +} + /* If FRONT is true, push at the front of the list. Use this for options added late in the process. */ static gpgme_error_t _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen, - int front, int *arg_locp) + int front, int *arg_locp, int gpg_arg) { struct arg_and_data_s *a; size_t prefixlen = prefix? strlen (prefix) : 0; @@ -241,28 +264,16 @@ _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen, a->data = NULL; a->dup_to = -1; a->arg_locp = arg_locp; + a->gpg_arg = gpg_arg; if (prefixlen) memcpy (a->arg, prefix, prefixlen); memcpy (a->arg + prefixlen, arg, arglen); a->arg[prefixlen + arglen] = 0; if (front) - { - a->next = gpg->arglist; - if (!gpg->arglist) - { - /* If this is the first argument, we need to update the tail - pointer. */ - gpg->argtail = &a->next; - } - gpg->arglist = a; - } + _prepend_to_arglist (gpg, a); else - { - a->next = NULL; - *gpg->argtail = a; - gpg->argtail = &a->next; - } + _append_to_arglist (gpg, a); return 0; } @@ -271,37 +282,50 @@ _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen, static gpgme_error_t add_arg_ext (engine_gpg_t gpg, const char *arg, int front) { - return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL); + return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL, 0); } static gpgme_error_t -add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp) +add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp, int front) { - return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp); + return _add_arg (gpg, NULL, arg, strlen (arg), front, locp, 0); } static gpgme_error_t add_arg (engine_gpg_t gpg, const char *arg) { - return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL); + return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL, 0); } static gpgme_error_t add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg) { - return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL); + return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL, 0); +} + +static gpgme_error_t +add_gpg_arg (engine_gpg_t gpg, const char *arg) +{ + return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL, 1); +} + +static gpgme_error_t +add_gpg_arg_with_value (engine_gpg_t gpg, const char *arg, const char *value, + int front) +{ + return _add_arg (gpg, arg, value, strlen (value), front, NULL, 1); } static gpgme_error_t add_arg_len (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen) { - return _add_arg (gpg, prefix, arg, arglen, 0, NULL); + return _add_arg (gpg, prefix, arg, arglen, 0, NULL, 0); } static gpgme_error_t -add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) +add_data_ext (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound, int front) { struct arg_and_data_s *a; @@ -311,7 +335,6 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) a = malloc (offsetof (struct arg_and_data_s, arg)); if (!a) return gpg_error_from_syserror (); - a->next = NULL; a->data = data; a->inbound = inbound; a->arg_locp = NULL; @@ -326,12 +349,22 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) a->print_fd = 0; a->dup_to = dup_to; } - *gpg->argtail = a; - gpg->argtail = &a->next; + + if (front) + _prepend_to_arglist (gpg, a); + else + _append_to_arglist (gpg, a); + return 0; } +static gpgme_error_t +add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound) +{ + return add_data_ext (gpg, data, dup_to, inbound, 0); +} + /* Return true if the engine's version is at least VERSION. */ static int have_gpg_version (engine_gpg_t gpg, const char *version) @@ -540,34 +573,18 @@ gpg_new (void **engine, const char *file_name, const char *home_dir, if (home_dir) { - rc = add_arg (gpg, "--homedir"); - if (!rc) - rc = add_arg (gpg, home_dir); + rc = add_gpg_arg_with_value (gpg, "--homedir=", home_dir, 0); if (rc) goto leave; } - rc = add_arg (gpg, "--status-fd"); - if (rc) - goto leave; - - { - char buf[25]; - _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]); - rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc); - if (rc) - goto leave; - } - - rc = add_arg (gpg, "--no-tty"); - if (!rc) - rc = add_arg (gpg, "--charset"); + rc = add_gpg_arg (gpg, "--no-tty"); if (!rc) - rc = add_arg (gpg, "utf8"); + rc = add_gpg_arg (gpg, "--charset=utf8"); if (!rc) - rc = add_arg (gpg, "--enable-progress-filter"); + rc = add_gpg_arg (gpg, "--enable-progress-filter"); if (!rc && have_gpg_version (gpg, "2.1.11")) - rc = add_arg (gpg, "--exit-on-status-write-error"); + rc = add_gpg_arg (gpg, "--exit-on-status-write-error"); if (rc) goto leave; @@ -576,9 +593,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_display) { - rc = add_arg (gpg, "--display"); - if (!rc) - rc = add_arg (gpg, dft_display); + rc = add_gpg_arg_with_value (gpg, "--display=", dft_display, 0); free (dft_display); if (rc) @@ -605,11 +620,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir, if (!err) { if (*dft_ttyname) - { - rc = add_arg (gpg, "--ttyname"); - if (!rc) - rc = add_arg (gpg, dft_ttyname); - } + rc = add_gpg_arg_with_value (gpg, "--ttyname=", dft_ttyname, 0); else rc = 0; if (!rc) @@ -619,11 +630,7 @@ gpg_new (void **engine, const char *file_name, const char *home_dir, goto leave; if (dft_ttytype) - { - rc = add_arg (gpg, "--ttytype"); - if (!rc) - rc = add_arg (gpg, dft_ttytype); - } + rc = add_gpg_arg_with_value (gpg, "--ttytype=", dft_ttytype, 0); free (dft_ttytype); } @@ -632,16 +639,6 @@ gpg_new (void **engine, const char *file_name, const char *home_dir, } } - rc = gpgme_data_new (&gpg->diagnostics); - if (rc) - goto leave; - - rc = add_arg (gpg, "--logger-fd"); - if (rc) - goto leave; - - rc = add_data (gpg, gpg->diagnostics, -2, 1); - leave: if (rc) gpg_release (gpg); @@ -871,9 +868,9 @@ build_argv (engine_gpg_t gpg, const char *pgmname) { gpgme_error_t err; struct arg_and_data_s *a; - struct fd_data_map_s *fd_data_map; + struct fd_data_map_s *fd_data_map = NULL; size_t datac=0, argc=0, allocated_argc=0; - char **argv; + char **argv = NULL; int need_special = 0; int use_agent = 0; char *p; @@ -907,7 +904,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argc++; /* For argv[0]. */ for (a = gpg->arglist; a; a = a->next) { - argc++; + argc += 1 + (gpg->flags.use_gpgtar && a->gpg_arg); if (a->data) { /*fprintf (stderr, "build_argv: data\n" );*/ @@ -926,26 +923,24 @@ build_argv (engine_gpg_t gpg, const char *pgmname) if (use_agent) argc++; if (*gpg->request_origin) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->auto_key_locate) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->trust_model) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->flags.no_symkey_cache) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->flags.ignore_mdc_error) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->flags.offline) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->flags.no_auto_check_trustdb) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (gpg->pinentry_mode) - argc++; + argc += 1 + !!gpg->flags.use_gpgtar; if (!gpg->cmd.used) argc++; /* --batch */ - argc++; /* --no-sk-comments */ - argv = calloc (argc + 1, sizeof *argv); allocated_argc = argc; @@ -954,19 +949,18 @@ build_argv (engine_gpg_t gpg, const char *pgmname) fd_data_map = calloc (datac + 1, sizeof *fd_data_map); if (!fd_data_map) { - int saved_err = gpg_error_from_syserror (); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc = datac = 0; argv[argc] = strdup (_gpgme_get_basename (pgmname)); /* argv[0] */ if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; if (need_special) @@ -974,10 +968,9 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argv[argc] = strdup ("--enable-special-filenames"); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } @@ -986,10 +979,9 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argv[argc] = strdup ("--use-agent"); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } @@ -998,92 +990,162 @@ build_argv (engine_gpg_t gpg, const char *pgmname) if (*gpg->request_origin) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = _gpgme_strconcat ("--request-origin=", gpg->request_origin, NULL); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->auto_key_locate) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup (gpg->auto_key_locate); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->trust_model) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup (gpg->trust_model); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->flags.no_symkey_cache) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } 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; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->flags.ignore_mdc_error) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup ("--ignore-mdc-error"); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->flags.offline) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } 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; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } if (gpg->flags.no_auto_check_trustdb) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup ("--no-auto-check-trustdb"); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } @@ -1101,13 +1163,23 @@ build_argv (engine_gpg_t gpg, const char *pgmname) } if (s) { + if (gpg->flags.use_gpgtar) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup (s); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } @@ -1118,22 +1190,12 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argv[argc] = strdup ("--batch"); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } - argv[argc] = strdup ("--no-sk-comments"); - if (!argv[argc]) - { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; - } - argc++; for (a = gpg->arglist; a; a = a->next) { if (a->arg_locp) @@ -1151,10 +1213,9 @@ build_argv (engine_gpg_t gpg, const char *pgmname) if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0) == -1) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } if (_gpgme_io_set_close_notify (fds[0], close_notify_handler, gpg) @@ -1202,10 +1263,9 @@ build_argv (engine_gpg_t gpg, const char *pgmname) argv[argc] = malloc (buflen); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } ptr = argv[argc]; @@ -1224,13 +1284,23 @@ build_argv (engine_gpg_t gpg, const char *pgmname) } else { + if (gpg->flags.use_gpgtar && a->gpg_arg) + { + argv[argc] = strdup ("--gpg-args"); + if (!argv[argc]) + { + err = gpg_error_from_syserror (); + if (err) + goto leave; + } + argc++; + } argv[argc] = strdup (a->arg); if (!argv[argc]) { - int saved_err = gpg_error_from_syserror (); - free (fd_data_map); - free_argv (argv); - return saved_err; + err = gpg_error_from_syserror (); + if (err) + goto leave; } argc++; } @@ -1241,9 +1311,18 @@ build_argv (engine_gpg_t gpg, const char *pgmname) allocated array like ccparray in gnupg. */ assert (argc <= allocated_argc); - gpg->argv = argv; - gpg->fd_data_map = fd_data_map; - return 0; +leave: + if (err) + { + free (fd_data_map); + free_argv (argv); + } + else + { + gpg->argv = argv; + gpg->fd_data_map = fd_data_map; + } + return err; } @@ -1561,28 +1640,65 @@ start (engine_gpg_t gpg) if (!gpg) return gpg_error (GPG_ERR_INV_VALUE); - if (!gpg->file_name && !_gpgme_get_default_gpg_name ()) + if (!gpg->flags.use_gpgtar) + pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name (); + else + pgmname = _gpgme_get_default_gpgtar_name (); + if (!pgmname) return trace_gpg_error (GPG_ERR_INV_ENGINE); + rc = gpgme_data_new (&gpg->diagnostics); + if (rc) + return rc; + + if (gpg->flags.use_gpgtar) + { + /* Read the diagnostics output from gpgtar's stderr. */ + rc = add_data (gpg, gpg->diagnostics, 2, 1); + if (rc) + return rc; + } + else + { + rc = add_data_ext (gpg, gpg->diagnostics, -2, 1, 1); + if (rc) + return rc; + + rc = add_arg_ext (gpg, "--logger-fd", 1); + if (rc) + return rc; + } + + if (!gpg->flags.use_gpgtar || have_gpg_version (gpg, "2.4.1")) + { + /* Do not pass --status-fd to gpgtar for gpg < 2.4.1. */ + { + char buf[25]; + _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]); + rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc, 1); + if (rc) + return rc; + } + + rc = add_arg_ext (gpg, "--status-fd", 1); + if (rc) + return rc; + } + if (gpg->lc_ctype) { - rc = add_arg_ext (gpg, gpg->lc_ctype, 1); - if (!rc) - rc = add_arg_ext (gpg, "--lc-ctype", 1); + rc = add_gpg_arg_with_value (gpg, "--lc-ctype=", gpg->lc_ctype, 1); if (rc) return rc; } if (gpg->lc_messages) { - rc = add_arg_ext (gpg, gpg->lc_messages, 1); - if (!rc) - rc = add_arg_ext (gpg, "--lc-messages", 1); + rc = add_gpg_arg_with_value (gpg, "--lc-messages=", gpg->lc_messages, 1); if (rc) return rc; } - pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name (); rc = build_argv (gpg, pgmname); if (rc) return rc; @@ -1714,6 +1830,14 @@ gpg_decrypt (void *engine, engine_gpg_t gpg = engine; gpgme_error_t err; + gpg->flags.use_gpgtar = !!(flags & GPGME_DECRYPT_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.4.1")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (gpg->flags.use_gpgtar && (flags & GPGME_DECRYPT_UNWRAP)) + return gpg_error (GPG_ERR_INV_VALUE); + err = add_arg (gpg, "--decrypt"); if (!err && (flags & GPGME_DECRYPT_UNWRAP)) @@ -1725,17 +1849,17 @@ gpg_decrypt (void *engine, } if (!err && export_session_key) - err = add_arg (gpg, "--show-session-key"); + err = add_gpg_arg (gpg, "--show-session-key"); if (!err && auto_key_retrieve) - err = add_arg (gpg, "--auto-key-retrieve"); + err = add_gpg_arg (gpg, "--auto-key-retrieve"); if (!err && gpg->flags.auto_key_import) - err = add_arg (gpg, "--auto-key-import"); + err = add_gpg_arg (gpg, "--auto-key-import"); if (!err && override_session_key && *override_session_key) { - if (have_gpg_version (gpg, "2.1.16")) + if (have_gpg_version (gpg, "2.1.16") && !gpg->flags.use_gpgtar) { gpgme_data_release (gpg->override_session_key); TRACE (DEBUG_ENGINE, "override", gpg, "seskey='%s' len=%zu\n", @@ -1765,25 +1889,43 @@ gpg_decrypt (void *engine, else { /* Using that option may leak the session key via ps(1). */ - err = add_arg (gpg, "--override-session-key"); - if (!err) - err = add_arg (gpg, override_session_key); + err = add_gpg_arg_with_value (gpg, "--override-session-key=", + override_session_key, 0); } } /* Tell the gpg object about the data. */ - if (!err) - err = add_arg (gpg, "--output"); - if (!err) - err = add_arg (gpg, "-"); - if (!err) - err = add_data (gpg, plain, 1, 1); - if (!err) - err = add_input_size_hint (gpg, ciph); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, ciph, -1, 0); + if (gpg->flags.use_gpgtar) + { + const char *file_name = gpgme_data_get_file_name (plain); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } + if (!err) + err = add_input_size_hint (gpg, ciph); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, ciph, 0, 0); + } + else + { + if (!err) + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, plain, 1, 1); + if (!err) + err = add_input_size_hint (gpg, ciph); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, ciph, -1, 0); + } if (!err) err = start (gpg); @@ -1867,16 +2009,11 @@ append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */) static gpgme_error_t append_args_from_sender (engine_gpg_t gpg, gpgme_ctx_t ctx) { - gpgme_error_t err; + gpgme_error_t err = 0; if (ctx->sender && have_gpg_version (gpg, "2.1.15")) - { - err = add_arg (gpg, "--sender"); - if (!err) - err = add_arg (gpg, ctx->sender); - } - else - err = 0; + err = add_gpg_arg_with_value (gpg, "--sender=", ctx->sender, 0); + return err; } @@ -1930,14 +2067,12 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */, if (!err) { if ((flags & NOTATION_FLAG_SET)) - err = add_arg (gpg, "--set-notation"); + err = add_gpg_arg_with_value (gpg, "--set-notation=", arg, 0); else if ((flags & NOTATION_FLAG_CERT)) - err = add_arg (gpg, "--cert-notation"); + err = add_gpg_arg_with_value (gpg, "--cert-notation=", arg, 0); else - err = add_arg (gpg, "--sig-notation"); + err = add_gpg_arg_with_value (gpg, "--sig-notation=", arg, 0); } - if (!err) - err = add_arg (gpg, arg); if (arg) free (arg); @@ -1964,9 +2099,7 @@ append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */, value = notation->value; if (!err) - err = add_arg (gpg, "--sig-policy-url"); - if (!err) - err = add_arg (gpg, value); + err = add_gpg_arg_with_value (gpg, "--sig-policy-url=", value, 0); if (value != notation->value) free (value); @@ -2199,6 +2332,14 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, engine_gpg_t gpg = engine; gpgme_error_t err = 0; + gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.4.1")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (gpg->flags.use_gpgtar && (flags & GPGME_ENCRYPT_WRAP)) + return gpg_error (GPG_ERR_INV_VALUE); + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); @@ -2206,7 +2347,7 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, err = add_arg (gpg, "--symmetric"); if (!err && use_armor) - err = add_arg (gpg, "--armor"); + err = add_gpg_arg (gpg, "--armor"); if (!err && (flags & GPGME_ENCRYPT_WRAP)) { @@ -2216,31 +2357,31 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, * the encryption would add an additional compression layer. * We better suppress that. */ flags |= GPGME_ENCRYPT_NO_COMPRESS; - err = add_arg (gpg, "--no-literal"); + err = add_gpg_arg (gpg, "--no-literal"); } if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) - err = add_arg (gpg, "--compress-algo=none"); + err = add_gpg_arg (gpg, "--compress-algo=none"); if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) - err = add_arg (gpg, "--throw-keyids"); + err = add_gpg_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"); + err = add_gpg_arg (gpg, "--mimemode"); if (!err && gpg->flags.include_key_block) - err = add_arg (gpg, "--include-key-block"); + err = add_gpg_arg (gpg, "--include-key-block"); if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) - err = add_arg (gpg, "--always-trust"); + err = add_gpg_arg (gpg, "--always-trust"); if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) - err = add_arg (gpg, "--no-encrypt-to"); + err = add_gpg_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) err = append_args_from_recipients_string (gpg, flags, recpstring); @@ -2255,19 +2396,39 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, err = add_arg (gpg, "-"); if (!err) err = add_data (gpg, ciph, 1, 1); - if (gpgme_data_get_file_name (plain)) + if (gpg->flags.use_gpgtar) { + const char *file_name = gpgme_data_get_file_name (plain); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } + if (!err) + err = add_arg (gpg, "--files-from"); + if (!err) + err = add_arg (gpg, "-"); + if (!err) + err = add_arg (gpg, "--null"); if (!err) - err = add_arg (gpg, "--set-filename"); + err = add_arg (gpg, "--utf8-strings"); + /* Pass the filenames to gpgtar's stdin. */ if (!err) - err = add_arg (gpg, gpgme_data_get_file_name (plain)); + err = add_data (gpg, plain, 0, 0); + } + else + { + const char *file_name = gpgme_data_get_file_name (plain); + if (!err && file_name) + err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0); + if (!err) + err = add_input_size_hint (gpg, plain); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, plain, -1, 0); } - if (!err) - err = add_input_size_hint (gpg, plain); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, plain, -1, 0); if (!err) err = start (gpg); @@ -2286,6 +2447,11 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], engine_gpg_t gpg = engine; gpgme_error_t err = 0; + gpg->flags.use_gpgtar = !!(flags & GPGME_ENCRYPT_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.4.1")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (recp || recpstring) err = add_arg (gpg, "--encrypt"); @@ -2295,30 +2461,30 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err) err = add_arg (gpg, "--sign"); if (!err && use_armor) - err = add_arg (gpg, "--armor"); + err = add_gpg_arg (gpg, "--armor"); if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) - err = add_arg (gpg, "--compress-algo=none"); + err = add_gpg_arg (gpg, "--compress-algo=none"); if (!err && (flags & GPGME_ENCRYPT_THROW_KEYIDS)) - err = add_arg (gpg, "--throw-keyids"); + err = add_gpg_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"); + err = add_gpg_arg (gpg, "--mimemode"); if (!err && gpg->flags.include_key_block) - err = add_arg (gpg, "--include-key-block"); + err = add_gpg_arg (gpg, "--include-key-block"); if (recp || recpstring) { /* If we know that all recipients are valid (full or ultimate trust) we can suppress further checks. */ if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST)) - err = add_arg (gpg, "--always-trust"); + err = add_gpg_arg (gpg, "--always-trust"); if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)) - err = add_arg (gpg, "--no-encrypt-to"); + err = add_gpg_arg (gpg, "--no-encrypt-to"); if (!err && !recp && recpstring) err = append_args_from_recipients_string (gpg, flags, recpstring); @@ -2342,19 +2508,39 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], err = add_arg (gpg, "-"); if (!err) err = add_data (gpg, ciph, 1, 1); - if (gpgme_data_get_file_name (plain)) + if (gpg->flags.use_gpgtar) { + const char *file_name = gpgme_data_get_file_name (plain); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } if (!err) - err = add_arg (gpg, "--set-filename"); + err = add_arg (gpg, "--files-from"); if (!err) - err = add_arg (gpg, gpgme_data_get_file_name (plain)); + err = add_arg (gpg, "-"); + if (!err) + err = add_arg (gpg, "--null"); + if (!err) + err = add_arg (gpg, "--utf8-strings"); + /* Pass the filenames to gpgtar's stdin. */ + if (!err) + err = add_data (gpg, plain, 0, 0); + } + else + { + const char *file_name = gpgme_data_get_file_name (plain); + if (!err && file_name) + err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0); + if (!err) + err = add_input_size_hint (gpg, plain); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, plain, -1, 0); } - if (!err) - err = add_input_size_hint (gpg, plain); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, plain, -1, 0); if (!err) err = start (gpg); @@ -3394,7 +3580,7 @@ gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy) static gpgme_error_t gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, - gpgme_sig_mode_t mode, int use_armor, int use_textmode, + gpgme_sig_mode_t flags, int use_armor, int use_textmode, int include_certs, gpgme_ctx_t ctx /* FIXME */) { engine_gpg_t gpg = engine; @@ -3402,27 +3588,36 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, (void)include_certs; - if (mode == GPGME_SIG_MODE_CLEAR) + if ((flags != GPGME_SIG_MODE_NORMAL) && (flags != GPGME_SIG_MODE_DETACH) + && (flags != GPGME_SIG_MODE_CLEAR) && (flags != GPGME_SIG_MODE_ARCHIVE)) + return gpg_error (GPG_ERR_INV_VALUE); + + gpg->flags.use_gpgtar = !!(flags & GPGME_SIG_MODE_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.4.1")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & GPGME_SIG_MODE_CLEAR) err = add_arg (gpg, "--clearsign"); else { err = add_arg (gpg, "--sign"); - if (!err && mode == GPGME_SIG_MODE_DETACH) + if (!err && (flags & GPGME_SIG_MODE_DETACH)) err = add_arg (gpg, "--detach"); if (!err && use_armor) - err = add_arg (gpg, "--armor"); + err = add_gpg_arg (gpg, "--armor"); if (!err) { if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME && have_gpg_version (gpg, "2.1.14")) - err = add_arg (gpg, "--mimemode"); + err = add_gpg_arg (gpg, "--mimemode"); else if (use_textmode) - err = add_arg (gpg, "--textmode"); + err = add_gpg_arg (gpg, "--textmode"); } } if (!err && gpg->flags.include_key_block) - err = add_arg (gpg, "--include-key-block"); + err = add_gpg_arg (gpg, "--include-key-block"); if (!err) err = append_args_from_signers (gpg, ctx); if (!err) @@ -3430,21 +3625,41 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, if (!err) err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_SIG); - if (gpgme_data_get_file_name (in)) + /* Tell the gpg object about the data. */ + if (gpg->flags.use_gpgtar) { + const char *file_name = gpgme_data_get_file_name (in); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } if (!err) - err = add_arg (gpg, "--set-filename"); + err = add_arg (gpg, "--files-from"); if (!err) - err = add_arg (gpg, gpgme_data_get_file_name (in)); + err = add_arg (gpg, "-"); + if (!err) + err = add_arg (gpg, "--null"); + if (!err) + err = add_arg (gpg, "--utf8-strings"); + /* Pass the filenames to gpgtar's stdin. */ + if (!err) + err = add_data (gpg, in, 0, 0); + } + else + { + const char *file_name = gpgme_data_get_file_name (in); + if (!err && file_name) + err = add_gpg_arg_with_value (gpg, "--set-filename=", file_name, 0); + if (!err) + err = add_input_size_hint (gpg, in); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, in, -1, 0); } - /* Tell the gpg object about the data. */ - if (!err) - err = add_input_size_hint (gpg, in); - if (!err) - err = add_arg (gpg, "--"); - if (!err) - err = add_data (gpg, in, -1, 0); if (!err) err = add_data (gpg, out, 1, 1); @@ -3455,20 +3670,43 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, } static gpgme_error_t -gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, - gpgme_data_t plaintext, gpgme_ctx_t ctx) +gpg_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig, + gpgme_data_t signed_text, gpgme_data_t plaintext, gpgme_ctx_t ctx) { engine_gpg_t gpg = engine; gpgme_error_t err; + gpg->flags.use_gpgtar = !!(flags & GPGME_VERIFY_ARCHIVE); + + if (gpg->flags.use_gpgtar && !have_gpg_version (gpg, "2.4.1")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + err = append_args_from_sender (gpg, ctx); if (!err && gpg->flags.auto_key_import) - err = add_arg (gpg, "--auto-key-import"); + err = add_gpg_arg (gpg, "--auto-key-import"); if (!err && ctx->auto_key_retrieve) - err = add_arg (gpg, "--auto-key-retrieve"); + err = add_gpg_arg (gpg, "--auto-key-retrieve"); if (err) ; + else if (gpg->flags.use_gpgtar) + { + const char *file_name = gpgme_data_get_file_name (plaintext); + if (!err && file_name) + { + err = add_arg (gpg, "--directory"); + if (!err) + err = add_arg (gpg, file_name); + } + /* gpgtar uses --decrypt also for signed-only archives */ + err = add_arg (gpg, "--decrypt"); + if (!err) + err = add_input_size_hint (gpg, sig); + if (!err) + err = add_arg (gpg, "--"); + if (!err) + err = add_data (gpg, sig, 0, 0); + } else if (plaintext) { /* Normal or cleartext signature. */ |