diff options
Diffstat (limited to '')
| -rw-r--r-- | src/ChangeLog | 12 | ||||
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/gpgme-tool.c | 122 | ||||
| -rw-r--r-- | src/gpgme.def | 1 | ||||
| -rw-r--r-- | src/gpgme.h.in | 6 | ||||
| -rw-r--r-- | src/libgpgme.vers | 2 | ||||
| -rw-r--r-- | src/vfs-create.c | 193 | ||||
| -rw-r--r-- | src/vfs-mount.c (renamed from src/g13.c) | 5 | 
8 files changed, 337 insertions, 6 deletions
| diff --git a/src/ChangeLog b/src/ChangeLog index 8c3689e7..bcfaa729 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2009-11-03  Marcus Brinkmann  <[email protected]> + +	* Makefile.am (main_sources): Change g13.c to vfs-mount.c.  Add +	vfs-create.c +	* vfs-create.c: New file. +	* g13.c: Renamed to ... +	* vfs-mount.c: ... this new file. +	* gpgme.h.in (gpgme_op_vfs_create): New prototype. +	* gpgme.def, libgpgme.vers: Add gpgme_op_vfs_create. +	* gpgme-tool.c (gt_vfs_create, cmd_vfs_create): New functions. +	(register_commands): Add VFS_CREATE and CREAET. +  2009-11-02  Marcus Brinkmann  <[email protected]>  	* debug.h (_gpgme_debug_buffer): Make TAG argument const const. diff --git a/src/Makefile.am b/src/Makefile.am index 677a8969..b1d93d36 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,7 +111,7 @@ main_sources =								\  	opassuan.c                                                      \  	engine.h engine-backend.h engine.c engine-gpg.c status-table.h	\  	$(gpgsm_components) $(assuan_components) $(gpgconf_components)  \ -	$(g13_components) g13.c						\ +	$(g13_components) vfs-mount.c vfs-create.c			\  	gpgconf.c							\  	sema.h priv-io.h $(system_components) dirinfo.c			\  	debug.c debug.h gpgme.c version.c error.c diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index e4948e28..7a41be08 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -483,6 +483,7 @@ typedef enum status      STATUS_TEXTMODE,      STATUS_INCLUDE_CERTS,      STATUS_KEYLIST_MODE, +    STATUS_RECIPIENT,      STATUS_ENCRYPT_RESULT    } status_t; @@ -495,6 +496,7 @@ const char *status_string[] =      "TEXTMODE",      "INCLUDE_CERTS",      "KEYLIST_MODE", +    "RECIPIENT",      "ENCRYPT_RESULT"    }; @@ -574,7 +576,88 @@ gt_signers_clear (gpgme_tool_t gt)  gpg_error_t -gt_recipients_add (gpgme_tool_t gt, const char *fpr) +gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key) +{ +  gpgme_ctx_t ctx; +  gpgme_ctx_t listctx; +  gpgme_error_t err; +  gpgme_key_t key; + +  if (!gt || !r_key || !pattern) +    return gpg_error (GPG_ERR_INV_VALUE); +   +  ctx = gt->ctx; + +  err = gpgme_new (&listctx); +  if (err) +    return err; + +  { +    gpgme_protocol_t proto; +    gpgme_engine_info_t info; + +    /* Clone the relevant state.  */ +    proto = gpgme_get_protocol (ctx); +    /* The g13 protocol does not allow keylisting, we need to choose +       something else.  */ +    if (proto == GPGME_PROTOCOL_G13) +      proto = GPGME_PROTOCOL_OpenPGP; + +    gpgme_set_protocol (listctx, proto); +    gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx)); +    info = gpgme_ctx_get_engine_info (ctx); +    while (info && info->protocol != proto) +      info = info->next; +    if (info) +      gpgme_ctx_set_engine_info (listctx, proto, +				 info->file_name, info->home_dir); +  } + +  err = gpgme_op_keylist_start (listctx, pattern, 0); +  if (!err) +    err = gpgme_op_keylist_next (listctx, r_key); +  if (!err) +    { +    try_next_key: +      err = gpgme_op_keylist_next (listctx, &key); +      if (gpgme_err_code (err) == GPG_ERR_EOF) +	err = 0; +      else +	{ +          if (!err +              && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr +              && key && key->subkeys && key->subkeys->fpr +              && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr)) +            { +              /* The fingerprint is identical.  We assume that this is +                 the same key and don't mark it as an ambiguous.  This +                 problem may occur with corrupted keyrings and has +                 been noticed often with gpgsm.  In fact gpgsm uses a +                 similar hack to sort out such duplicates but it can't +                 do that while listing keys.  */ +              gpgme_key_unref (key); +              goto try_next_key; +            } +	  if (!err) +	    { +	      gpgme_key_unref (key); +	      err = gpg_error (GPG_ERR_AMBIGUOUS_NAME); +	    } +	  gpgme_key_unref (*r_key); +	} +    } +  gpgme_release (listctx); +   +  if (! err) +    gt_write_status (gt, STATUS_RECIPIENT,  +		     ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?  +		     (*r_key)->subkeys->fpr : "invalid", NULL); +  return err; +} + + +gpg_error_t +gt_recipients_add (gpgme_tool_t gt, const char *pattern)  {    gpg_error_t err;    gpgme_key_t key; @@ -582,7 +665,7 @@ gt_recipients_add (gpgme_tool_t gt, const char *fpr)    if (gt->recipients_nr >= MAX_RECIPIENTS)      return gpg_error_from_errno (ENOMEM); -  err = gpgme_get_key (gt->ctx, fpr, &key, 0); +  err = gt_get_key (gt, pattern, &key);    if (err)      return err; @@ -962,6 +1045,18 @@ gt_vfs_mount (gpgme_tool_t gt, const char *container_file,  } +gpg_error_t +gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags) +{ +  gpg_error_t err; +  gpg_error_t op_err; +  err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file, +			     flags, &op_err); +  gt_recipients_clear (gt); +  return err || op_err; +} + +  // TODO  #define GT_RESULT_ENCRYPT 0x1  #define GT_RESULT_DECRYPT 0x2 @@ -1743,6 +1838,27 @@ cmd_vfs_mount (assuan_context_t ctx, char *line)  static gpg_error_t +cmd_vfs_create (assuan_context_t ctx, char *line) +{ +  struct server *server = assuan_get_pointer (ctx); +  gpg_error_t err; +  char *end; + +  end = strchr (line, ' '); +  if (end) +    { +      *(end++) = '\0'; +      while (*end == ' ') +	end++; +    } + +  err = gt_vfs_create (server->gt, line, 0); + +  return err; +} + + +static gpg_error_t  cmd_result (assuan_context_t ctx, char *line)  {    struct server *server = assuan_get_pointer (ctx); @@ -1835,6 +1951,8 @@ register_commands (assuan_context_t ctx)      // TODO: ASSUAN      { "VFS_MOUNT", cmd_vfs_mount },      { "MOUNT", cmd_vfs_mount }, +    { "VFS_CREATE", cmd_vfs_create }, +    { "CREATE", cmd_vfs_create },      // TODO: GPGCONF      { "RESULT", cmd_result },      { "STRERROR", cmd_strerror }, diff --git a/src/gpgme.def b/src/gpgme.def index 6d223f4d..816da318 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -190,6 +190,7 @@ EXPORTS      gpgme_wait_ext			  @145      gpgme_op_vfs_mount_result		  @146      gpgme_op_vfs_mount			  @147 +    gpgme_op_vfs_create			  @148  ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 42b9237f..f0a61d79 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1808,9 +1808,13 @@ gpgme_vfs_mount_result_t gpgme_op_vfs_mount_result (gpgme_ctx_t ctx);     or destroyed.  Transmission errors are returned directly,     operational errors are returned in OP_ERR.  */  gpgme_error_t gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, -				  const char *mount_dir, int flags, +				  const char *mount_dir, unsigned int flags,  				  gpgme_error_t *op_err); +gpgme_error_t gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], +				   const char *container_file, +				   unsigned int flags, gpgme_error_t *op_err); +  /* Interface to gpgconf(1).  */ diff --git a/src/libgpgme.vers b/src/libgpgme.vers index 9989c75b..24107d48 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -71,6 +71,8 @@ GPGME_1.1 {      gpgme_op_vfs_mount_result;      gpgme_op_vfs_mount; +    gpgme_op_vfs_create; +  }; diff --git a/src/vfs-create.c b/src/vfs-create.c new file mode 100644 index 00000000..a965a964 --- /dev/null +++ b/src/vfs-create.c @@ -0,0 +1,193 @@ +/* vfs-create.c - vfs create support in GPGME +   Copyright (C) 2009 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.  */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> + +#include "gpgme.h" +#include "debug.h" +#include "context.h" +#include "ops.h" +#include "util.h" + +static gpgme_error_t +vfs_start (gpgme_ctx_t ctx, int synchronous, +	   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_error_t err; + +  if (!command || !*command) +    return gpg_error (GPG_ERR_INV_VALUE); + +  /* The flag value 256 is used to suppress an engine reset.  This is +     required to keep the connection running.  */ +  err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256)); +  if (err) +    return err; + +  return _gpgme_engine_op_assuan_transact (ctx->engine, command, +					   data_cb, data_cb_value, +					   inq_cb, inq_cb_value, +					   status_cb, status_cb_value); +} + + + +/* XXXX.  This is the asynchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_transact_start (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) +{ +  return vfs_start (ctx, 0, command, data_cb, data_cb_value, +		    inq_cb, inq_cb_value, status_cb, status_cb_value); +} + + +/* XXXX.  This is the synchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_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_error_t *op_err) +{ +  gpgme_error_t err; +   +  err = vfs_start (ctx, 1, command, data_cb, data_cb_value, +		   inq_cb, inq_cb_value, status_cb, status_cb_value); +  if (!err) +    err = _gpgme_wait_one_ext (ctx, op_err); +  return err; +} + + +/* The actual exported interface follows.  */ + +/* The container is automatically uncreateed when the context is reset +   or destroyed.  This is a synchronous convenience interface, which +   automatically returns an operation error if there is no +   transmission error.  */ +static gpgme_error_t +_gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], +		      const char *container_file, unsigned int flags, +		      gpgme_error_t *op_err) +{ +  gpg_error_t err; +  char *cmd; +  char *container_file_esc = NULL; +  int i; + +  /* We want to encourage people to check error values, so not getting +     them is discouraged here.  Also makes our code easier.  */ +  if (! op_err) +    return gpg_error (GPG_ERR_INV_VALUE); + +  err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0); +  if (err) +    return err; + +  i = 0; +  while (!err && recp[i]) +    { +      if (!recp[i]->subkeys || !recp[i]->subkeys->fpr) +	{ +	  free (container_file_esc); +	  return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); +	} + +      if (asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0) +	{ +	  err = gpg_error_from_syserror (); +	  free (container_file_esc); +	  return err; +	} +       +      err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, +				   NULL, NULL, op_err); +      free (cmd); +      if (err || *op_err) +	{ +	  free (container_file_esc); +	  return err; +	} +      recp++; +    } + +  if (asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0) +    { +      err = gpg_error_from_syserror (); +      free (container_file_esc); +      return err; +    } +  free (container_file_esc); +     +  err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, +			       NULL, NULL, op_err); +  free (cmd); + +  return err; +} + + +gpgme_error_t +gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], +		      const char *container_file, unsigned int flags, +		      gpgme_error_t *op_err) +{ +  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_vfs_create", ctx, +	      "container_file=%s, flags=0x%x, op_err=%p", +	      container_file, flags, op_err); + +  if (_gpgme_debug_trace () && recp) +    { +      int i = 0; + +      while (recp[i]) +	{ +	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], +		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ?  +		      recp[i]->subkeys->fpr : "invalid"); +	  i++; +	} +    } + +  return TRACE_ERR (_gpgme_op_vfs_create (ctx, recp, container_file, +					  flags, op_err)); +} + diff --git a/src/g13.c b/src/vfs-mount.c index a2ab675e..3c0b6f24 100644 --- a/src/g13.c +++ b/src/vfs-mount.c @@ -1,4 +1,4 @@ -/* g13.c - g13 support in GPGME +/* vfs-mount.c - vfs mount support in GPGME     Copyright (C) 2009 g10 Code GmbH     This file is part of GPGME. @@ -198,7 +198,8 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,  gpgme_error_t  gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, -		     const char *mount_dir, int flags, gpgme_error_t *op_err) +		    const char *mount_dir, unsigned int flags, +		    gpgme_error_t *op_err)  {    TRACE_BEG4 (DEBUG_CTX, "gpgme_op_vfs_mount", ctx,  	      "container=%s, mount_dir=%s, flags=0x%x, op_err=%p", | 
