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:
parent
490661821a
commit
97932b102a
@ -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.
|
||||
|
@ -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
|
||||
|
122
src/gpgme-tool.c
122
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
|
||||
@ -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 },
|
||||
|
@ -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
|
||||
|
||||
|
@ -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). */
|
||||
|
||||
|
@ -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
193
src/vfs-create.c
Normal 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));
|
||||
}
|
||||
|
@ -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",
|
Loading…
Reference in New Issue
Block a user