2009-11-03 Marcus Brinkmann <marcus@g10code.de>

* 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.
This commit is contained in:
Marcus Brinkmann 2009-11-03 19:15:35 +00:00
parent 490661821a
commit 97932b102a
8 changed files with 337 additions and 6 deletions

View File

@ -1,3 +1,15 @@
2009-11-03 Marcus Brinkmann <marcus@g10code.de>
* 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 <marcus@g10code.de>
* debug.h (_gpgme_debug_buffer): Make TAG argument const const.

View File

@ -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

View File

@ -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
@ -1742,6 +1837,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)
{
@ -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 },

View File

@ -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

View File

@ -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). */

View File

@ -71,6 +71,8 @@ GPGME_1.1 {
gpgme_op_vfs_mount_result;
gpgme_op_vfs_mount;
gpgme_op_vfs_create;
};

193
src/vfs-create.c Normal file
View File

@ -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));
}

View File

@ -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",